@codexa/cli 8.5.0 → 8.6.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.
- package/commands/architect.ts +760 -896
- package/commands/check.ts +131 -131
- package/commands/clear.ts +170 -174
- package/commands/decide.ts +249 -249
- package/commands/discover.ts +82 -10
- package/commands/knowledge.ts +361 -361
- package/commands/patterns.ts +621 -621
- package/commands/plan.ts +376 -376
- package/commands/product.ts +626 -628
- package/commands/research.ts +754 -754
- package/commands/review.ts +463 -463
- package/commands/standards.ts +200 -223
- package/commands/task.ts +2 -2
- package/commands/utils.ts +1021 -1021
- package/db/connection.ts +32 -32
- package/db/schema.ts +719 -788
- package/detectors/loader.ts +0 -12
- package/gates/standards-validator.ts +204 -204
- package/gates/validator.ts +441 -441
- package/package.json +43 -43
- package/protocol/process-return.ts +450 -450
- package/protocol/subagent-protocol.ts +401 -411
- package/workflow.ts +0 -18
package/db/schema.ts
CHANGED
|
@@ -1,788 +1,719 @@
|
|
|
1
|
-
import { getDb } from "./connection";
|
|
2
|
-
|
|
3
|
-
export function initSchema(): void {
|
|
4
|
-
const db = getDb();
|
|
5
|
-
|
|
6
|
-
db.exec(`
|
|
7
|
-
-- 1. Feature sendo desenvolvida
|
|
8
|
-
CREATE TABLE IF NOT EXISTS specs (
|
|
9
|
-
id TEXT PRIMARY KEY,
|
|
10
|
-
name TEXT NOT NULL,
|
|
11
|
-
phase TEXT NOT NULL DEFAULT 'planning',
|
|
12
|
-
approved_at TEXT,
|
|
13
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
14
|
-
updated_at TEXT
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- 2. Contexto compartilhado (o coracao do sistema)
|
|
18
|
-
CREATE TABLE IF NOT EXISTS context (
|
|
19
|
-
spec_id TEXT PRIMARY KEY REFERENCES specs(id),
|
|
20
|
-
objective TEXT NOT NULL,
|
|
21
|
-
approach TEXT,
|
|
22
|
-
constraints TEXT,
|
|
23
|
-
patterns TEXT,
|
|
24
|
-
current_task INTEGER,
|
|
25
|
-
total_tasks INTEGER,
|
|
26
|
-
last_checkpoint TEXT,
|
|
27
|
-
updated_at TEXT
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
-- 3. Tarefas com dependencias (para paralelizacao)
|
|
31
|
-
CREATE TABLE IF NOT EXISTS tasks (
|
|
32
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
33
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
34
|
-
number INTEGER NOT NULL,
|
|
35
|
-
name TEXT NOT NULL,
|
|
36
|
-
depends_on TEXT,
|
|
37
|
-
can_parallel INTEGER DEFAULT 1,
|
|
38
|
-
agent TEXT,
|
|
39
|
-
files TEXT,
|
|
40
|
-
status TEXT DEFAULT 'pending',
|
|
41
|
-
checkpoint TEXT,
|
|
42
|
-
completed_at TEXT,
|
|
43
|
-
UNIQUE(spec_id, number)
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
-- 4. Decisoes (registro critico)
|
|
47
|
-
CREATE TABLE IF NOT EXISTS decisions (
|
|
48
|
-
id TEXT PRIMARY KEY,
|
|
49
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
50
|
-
task_ref INTEGER,
|
|
51
|
-
title TEXT NOT NULL,
|
|
52
|
-
decision TEXT NOT NULL,
|
|
53
|
-
rationale TEXT,
|
|
54
|
-
status TEXT DEFAULT 'active',
|
|
55
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
-- 5. Artefatos
|
|
59
|
-
CREATE TABLE IF NOT EXISTS artifacts (
|
|
60
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
61
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
62
|
-
task_ref INTEGER NOT NULL,
|
|
63
|
-
path TEXT NOT NULL,
|
|
64
|
-
action TEXT NOT NULL,
|
|
65
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
66
|
-
UNIQUE(spec_id, path)
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
-- 6. Review (fase REV)
|
|
70
|
-
CREATE TABLE IF NOT EXISTS review (
|
|
71
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
72
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
73
|
-
planned_vs_done TEXT,
|
|
74
|
-
deviations TEXT,
|
|
75
|
-
pattern_violations TEXT,
|
|
76
|
-
status TEXT DEFAULT 'pending',
|
|
77
|
-
resolution TEXT,
|
|
78
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
-- 7. Snapshots (recovery)
|
|
82
|
-
CREATE TABLE IF NOT EXISTS snapshots (
|
|
83
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
84
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
85
|
-
data TEXT NOT NULL,
|
|
86
|
-
trigger TEXT NOT NULL,
|
|
87
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
-- 8. Projeto (informacoes detectadas no discover)
|
|
91
|
-
CREATE TABLE IF NOT EXISTS project (
|
|
92
|
-
id TEXT PRIMARY KEY DEFAULT 'default',
|
|
93
|
-
name TEXT,
|
|
94
|
-
stack TEXT NOT NULL,
|
|
95
|
-
discovered_at TEXT,
|
|
96
|
-
updated_at TEXT
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
-- 9. Standards do projeto
|
|
100
|
-
CREATE TABLE IF NOT EXISTS standards (
|
|
101
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
102
|
-
category TEXT NOT NULL,
|
|
103
|
-
scope TEXT NOT NULL,
|
|
104
|
-
rule TEXT NOT NULL,
|
|
105
|
-
examples TEXT,
|
|
106
|
-
anti_examples TEXT,
|
|
107
|
-
enforcement TEXT DEFAULT 'required',
|
|
108
|
-
source TEXT,
|
|
109
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
-- 10. Knowledge broadcast (compartilhamento em tempo real)
|
|
113
|
-
CREATE TABLE IF NOT EXISTS knowledge (
|
|
114
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
115
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
116
|
-
task_origin INTEGER NOT NULL,
|
|
117
|
-
category TEXT NOT NULL,
|
|
118
|
-
content TEXT NOT NULL,
|
|
119
|
-
severity TEXT DEFAULT 'info',
|
|
120
|
-
broadcast_to TEXT DEFAULT 'all',
|
|
121
|
-
acknowledged_by TEXT,
|
|
122
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
-- 11. Gate bypass log (auditoria de bypasses)
|
|
126
|
-
CREATE TABLE IF NOT EXISTS gate_bypasses (
|
|
127
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
128
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
129
|
-
task_id INTEGER NOT NULL,
|
|
130
|
-
gate_name TEXT NOT NULL,
|
|
131
|
-
reason TEXT,
|
|
132
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
-- 12. Product context (PRD/contexto de produto)
|
|
136
|
-
CREATE TABLE IF NOT EXISTS product_context (
|
|
137
|
-
id TEXT PRIMARY KEY DEFAULT 'default',
|
|
138
|
-
name TEXT NOT NULL,
|
|
139
|
-
problem TEXT NOT NULL,
|
|
140
|
-
solution TEXT,
|
|
141
|
-
target_users TEXT,
|
|
142
|
-
value_proposition TEXT,
|
|
143
|
-
success_metrics TEXT,
|
|
144
|
-
out_of_scope TEXT,
|
|
145
|
-
constraints TEXT,
|
|
146
|
-
source TEXT DEFAULT 'guide',
|
|
147
|
-
discovered_at TEXT,
|
|
148
|
-
updated_at TEXT
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
-- 13. Product goals (objetivos do produto)
|
|
152
|
-
CREATE TABLE IF NOT EXISTS product_goals (
|
|
153
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
154
|
-
product_id TEXT NOT NULL DEFAULT 'default' REFERENCES product_context(id),
|
|
155
|
-
category TEXT NOT NULL,
|
|
156
|
-
goal TEXT NOT NULL,
|
|
157
|
-
priority TEXT DEFAULT 'medium',
|
|
158
|
-
status TEXT DEFAULT 'active',
|
|
159
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
-- 14. Product features (features core do produto)
|
|
163
|
-
CREATE TABLE IF NOT EXISTS product_features (
|
|
164
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
165
|
-
product_id TEXT NOT NULL DEFAULT 'default' REFERENCES product_context(id),
|
|
166
|
-
name TEXT NOT NULL,
|
|
167
|
-
description TEXT,
|
|
168
|
-
priority TEXT DEFAULT 'medium',
|
|
169
|
-
status TEXT DEFAULT 'planned',
|
|
170
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
-- 15. Library contexts (contexto atualizado por biblioteca)
|
|
174
|
-
CREATE TABLE IF NOT EXISTS lib_contexts (
|
|
175
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
176
|
-
lib_name TEXT NOT NULL UNIQUE,
|
|
177
|
-
version TEXT NOT NULL,
|
|
178
|
-
context_file TEXT NOT NULL,
|
|
179
|
-
source_url TEXT,
|
|
180
|
-
researched_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
181
|
-
updated_at TEXT
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
-- 16. Agent lib mappings (quais libs cada agente carrega)
|
|
185
|
-
CREATE TABLE IF NOT EXISTS agent_lib_mappings (
|
|
186
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
187
|
-
agent_type TEXT NOT NULL,
|
|
188
|
-
lib_name TEXT NOT NULL,
|
|
189
|
-
priority INTEGER DEFAULT 0,
|
|
190
|
-
UNIQUE(agent_type, lib_name)
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
-- 17. Implementation patterns (padroes extraidos do codigo - v7.4)
|
|
194
|
-
CREATE TABLE IF NOT EXISTS implementation_patterns (
|
|
195
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
196
|
-
|
|
197
|
-
-- Identificacao
|
|
198
|
-
category TEXT NOT NULL, -- component, hook, service, route, schema, test, action
|
|
199
|
-
name TEXT NOT NULL UNIQUE, -- ex: "page-component", "data-hook", "api-route"
|
|
200
|
-
|
|
201
|
-
-- Contexto
|
|
202
|
-
scope TEXT NOT NULL, -- frontend, backend, database, testing
|
|
203
|
-
applies_to TEXT NOT NULL, -- glob pattern: "app/**/page.tsx", "src/hooks/*.ts"
|
|
204
|
-
|
|
205
|
-
-- O Padrao Extraido
|
|
206
|
-
structure TEXT NOT NULL, -- JSON com estrutura comum (imports, exports, patterns, conventions)
|
|
207
|
-
template TEXT NOT NULL, -- Template de codigo com placeholders
|
|
208
|
-
examples TEXT NOT NULL, -- JSON array de arquivos que seguem este padrao
|
|
209
|
-
|
|
210
|
-
-- Anti-patterns identificados
|
|
211
|
-
anti_patterns TEXT, -- JSON array de anti-patterns encontrados
|
|
212
|
-
|
|
213
|
-
-- Metadados
|
|
214
|
-
confidence REAL DEFAULT 0.8, -- 0-1, baseado em quantos arquivos seguem
|
|
215
|
-
extracted_from INTEGER, -- Quantos arquivos foram analisados
|
|
216
|
-
|
|
217
|
-
-- Auditoria
|
|
218
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
219
|
-
updated_at TEXT
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
-- 18. Knowledge Graph (v8.0 - Relacoes entre entidades)
|
|
223
|
-
CREATE TABLE IF NOT EXISTS knowledge_graph (
|
|
224
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
225
|
-
spec_id TEXT REFERENCES specs(id),
|
|
226
|
-
|
|
227
|
-
-- No de origem
|
|
228
|
-
source_type TEXT NOT NULL, -- file, decision, pattern, task, artifact
|
|
229
|
-
source_id TEXT NOT NULL,
|
|
230
|
-
|
|
231
|
-
-- No de destino
|
|
232
|
-
target_type TEXT NOT NULL,
|
|
233
|
-
target_id TEXT NOT NULL,
|
|
234
|
-
|
|
235
|
-
-- Relacao
|
|
236
|
-
relation TEXT NOT NULL, -- uses, implements, depends_on, modifies, contradicts, extracted_from
|
|
237
|
-
|
|
238
|
-
-- Metadados
|
|
239
|
-
strength REAL DEFAULT 1.0, -- 0-1, peso da relacao
|
|
240
|
-
metadata TEXT, -- JSON com informacoes adicionais
|
|
241
|
-
|
|
242
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
-- 19. Reasoning Log (v8.0 - Historico de raciocinio)
|
|
246
|
-
CREATE TABLE IF NOT EXISTS reasoning_log (
|
|
247
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
248
|
-
spec_id TEXT REFERENCES specs(id),
|
|
249
|
-
task_id INTEGER REFERENCES tasks(id),
|
|
250
|
-
|
|
251
|
-
-- O raciocinio
|
|
252
|
-
category TEXT NOT NULL, -- decision, discovery, error, success, challenge, recommendation
|
|
253
|
-
thought TEXT NOT NULL, -- "Escolhi X porque Y"
|
|
254
|
-
|
|
255
|
-
-- Contexto
|
|
256
|
-
related_files TEXT, -- JSON array de arquivos
|
|
257
|
-
related_decisions TEXT, -- JSON array de decision IDs
|
|
258
|
-
related_patterns TEXT, -- JSON array de pattern names
|
|
259
|
-
|
|
260
|
-
-- Importancia
|
|
261
|
-
importance TEXT DEFAULT 'normal', -- critical, high, normal, low
|
|
262
|
-
|
|
263
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
-- 20. Session Summaries (v8.0 - Resumos de sessao para continuidade)
|
|
267
|
-
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
268
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
269
|
-
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
270
|
-
|
|
271
|
-
-- Periodo
|
|
272
|
-
start_time TEXT NOT NULL,
|
|
273
|
-
end_time TEXT NOT NULL,
|
|
274
|
-
|
|
275
|
-
-- Conteudo
|
|
276
|
-
summary TEXT NOT NULL, -- O que foi feito
|
|
277
|
-
decisions TEXT, -- JSON array de decisoes tomadas
|
|
278
|
-
blockers TEXT, -- JSON array de problemas encontrados
|
|
279
|
-
next_steps TEXT, -- JSON array de recomendacoes
|
|
280
|
-
|
|
281
|
-
-- Estatisticas
|
|
282
|
-
tasks_completed INTEGER DEFAULT 0,
|
|
283
|
-
files_created INTEGER DEFAULT 0,
|
|
284
|
-
files_modified INTEGER DEFAULT 0,
|
|
285
|
-
|
|
286
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
-- 21. Architectural Analyses (v8.1 - migrado de architect.ts para schema central)
|
|
290
|
-
CREATE TABLE IF NOT EXISTS architectural_analyses (
|
|
291
|
-
id TEXT PRIMARY KEY,
|
|
292
|
-
name TEXT NOT NULL,
|
|
293
|
-
description TEXT NOT NULL,
|
|
294
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
295
|
-
|
|
296
|
-
-- Conteudo JSON
|
|
297
|
-
context TEXT,
|
|
298
|
-
current_architecture TEXT,
|
|
299
|
-
approach TEXT,
|
|
300
|
-
chosen_alternative TEXT,
|
|
301
|
-
diagrams TEXT, -- JSON array
|
|
302
|
-
baby_steps TEXT, -- JSON array
|
|
303
|
-
risks TEXT, -- JSON array
|
|
304
|
-
alternatives TEXT, -- JSON array
|
|
305
|
-
decisions TEXT, -- JSON array
|
|
306
|
-
|
|
307
|
-
-- Arquivo gerado
|
|
308
|
-
file_path TEXT,
|
|
309
|
-
|
|
310
|
-
-- Timestamps
|
|
311
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
312
|
-
updated_at TEXT,
|
|
313
|
-
approved_at TEXT
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
-- 22. Project Utilities (v8.5 - DRY enforcement utility map)
|
|
317
|
-
CREATE TABLE IF NOT EXISTS project_utilities (
|
|
318
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
319
|
-
file_path TEXT NOT NULL,
|
|
320
|
-
utility_name TEXT NOT NULL,
|
|
321
|
-
utility_type TEXT NOT NULL,
|
|
322
|
-
scope TEXT NOT NULL,
|
|
323
|
-
signature TEXT,
|
|
324
|
-
description TEXT,
|
|
325
|
-
spec_id TEXT,
|
|
326
|
-
task_ref INTEGER,
|
|
327
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
328
|
-
updated_at TEXT,
|
|
329
|
-
UNIQUE(file_path, utility_name)
|
|
330
|
-
);
|
|
331
|
-
|
|
332
|
-
-- Indices para performance
|
|
333
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_spec ON tasks(spec_id);
|
|
334
|
-
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
335
|
-
CREATE INDEX IF NOT EXISTS idx_decisions_spec ON decisions(spec_id);
|
|
336
|
-
CREATE INDEX IF NOT EXISTS idx_artifacts_spec ON artifacts(spec_id);
|
|
337
|
-
CREATE INDEX IF NOT EXISTS idx_snapshots_spec ON snapshots(spec_id);
|
|
338
|
-
CREATE INDEX IF NOT EXISTS idx_standards_category ON standards(category);
|
|
339
|
-
CREATE INDEX IF NOT EXISTS idx_standards_scope ON standards(scope);
|
|
340
|
-
CREATE INDEX IF NOT EXISTS idx_knowledge_spec ON knowledge(spec_id);
|
|
341
|
-
CREATE INDEX IF NOT EXISTS idx_knowledge_category ON knowledge(category);
|
|
342
|
-
CREATE INDEX IF NOT EXISTS idx_knowledge_severity ON knowledge(severity);
|
|
343
|
-
CREATE INDEX IF NOT EXISTS idx_gate_bypasses_spec ON gate_bypasses(spec_id);
|
|
344
|
-
CREATE INDEX IF NOT EXISTS idx_product_goals_product ON product_goals(product_id);
|
|
345
|
-
CREATE INDEX IF NOT EXISTS idx_product_goals_category ON product_goals(category);
|
|
346
|
-
CREATE INDEX IF NOT EXISTS idx_product_features_product ON product_features(product_id);
|
|
347
|
-
CREATE INDEX IF NOT EXISTS idx_product_features_priority ON product_features(priority);
|
|
348
|
-
CREATE INDEX IF NOT EXISTS idx_lib_contexts_lib ON lib_contexts(lib_name);
|
|
349
|
-
CREATE INDEX IF NOT EXISTS idx_agent_lib_mappings_agent ON agent_lib_mappings(agent_type);
|
|
350
|
-
CREATE INDEX IF NOT EXISTS idx_impl_patterns_category ON implementation_patterns(category);
|
|
351
|
-
CREATE INDEX IF NOT EXISTS idx_impl_patterns_scope ON implementation_patterns(scope);
|
|
352
|
-
CREATE INDEX IF NOT EXISTS idx_impl_patterns_name ON implementation_patterns(name);
|
|
353
|
-
|
|
354
|
-
-- v8.0: Indices para Knowledge Graph
|
|
355
|
-
CREATE INDEX IF NOT EXISTS idx_kg_source ON knowledge_graph(source_type, source_id);
|
|
356
|
-
CREATE INDEX IF NOT EXISTS idx_kg_target ON knowledge_graph(target_type, target_id);
|
|
357
|
-
CREATE INDEX IF NOT EXISTS idx_kg_relation ON knowledge_graph(relation);
|
|
358
|
-
CREATE INDEX IF NOT EXISTS idx_kg_spec ON knowledge_graph(spec_id);
|
|
359
|
-
|
|
360
|
-
-- v8.0: Indices para Reasoning Log
|
|
361
|
-
CREATE INDEX IF NOT EXISTS idx_reasoning_spec ON reasoning_log(spec_id);
|
|
362
|
-
CREATE INDEX IF NOT EXISTS idx_reasoning_task ON reasoning_log(task_id);
|
|
363
|
-
CREATE INDEX IF NOT EXISTS idx_reasoning_category ON reasoning_log(category);
|
|
364
|
-
CREATE INDEX IF NOT EXISTS idx_reasoning_importance ON reasoning_log(importance);
|
|
365
|
-
|
|
366
|
-
-- v8.0: Indices para Session Summaries
|
|
367
|
-
CREATE INDEX IF NOT EXISTS idx_session_spec ON session_summaries(spec_id);
|
|
368
|
-
CREATE INDEX IF NOT EXISTS idx_session_time ON session_summaries(end_time);
|
|
369
|
-
|
|
370
|
-
-- v8.1: Indices para Architectural Analyses
|
|
371
|
-
CREATE INDEX IF NOT EXISTS idx_arch_status ON architectural_analyses(status);
|
|
372
|
-
CREATE INDEX IF NOT EXISTS idx_arch_created ON architectural_analyses(created_at);
|
|
373
|
-
|
|
374
|
-
-- v8.5: Indices para Project Utilities
|
|
375
|
-
CREATE INDEX IF NOT EXISTS idx_utils_scope ON project_utilities(scope);
|
|
376
|
-
CREATE INDEX IF NOT EXISTS idx_utils_name ON project_utilities(utility_name);
|
|
377
|
-
CREATE INDEX IF NOT EXISTS idx_utils_file ON project_utilities(file_path);
|
|
378
|
-
`);
|
|
379
|
-
|
|
380
|
-
// v8.4: Migracao - adicionar analysis_id na tabela specs
|
|
381
|
-
try {
|
|
382
|
-
db.exec(`ALTER TABLE specs ADD COLUMN analysis_id TEXT`);
|
|
383
|
-
} catch {
|
|
384
|
-
// Coluna ja existe - ignorar
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export function
|
|
389
|
-
const db = getDb();
|
|
390
|
-
db.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
export
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
const db = getDb();
|
|
721
|
-
const now = new Date().toISOString();
|
|
722
|
-
db.run(
|
|
723
|
-
`INSERT INTO project_utilities (file_path, utility_name, utility_type, scope, signature, description, spec_id, task_ref, created_at, updated_at)
|
|
724
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
725
|
-
ON CONFLICT(file_path, utility_name) DO UPDATE SET
|
|
726
|
-
utility_type = excluded.utility_type,
|
|
727
|
-
scope = excluded.scope,
|
|
728
|
-
signature = COALESCE(excluded.signature, project_utilities.signature),
|
|
729
|
-
description = COALESCE(excluded.description, project_utilities.description),
|
|
730
|
-
updated_at = excluded.updated_at`,
|
|
731
|
-
[
|
|
732
|
-
utility.filePath, utility.utilityName, utility.utilityType, utility.scope,
|
|
733
|
-
utility.signature || null, utility.description || null,
|
|
734
|
-
specId || null, taskRef || null, now, now,
|
|
735
|
-
]
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
export function getUtilitiesForContext(
|
|
740
|
-
dirs: string[],
|
|
741
|
-
scope?: string,
|
|
742
|
-
limit: number = 15
|
|
743
|
-
): any[] {
|
|
744
|
-
const db = getDb();
|
|
745
|
-
|
|
746
|
-
// Se nenhum filtro, retornar mais recentes
|
|
747
|
-
if (dirs.length === 0 && !scope) {
|
|
748
|
-
return db.query(
|
|
749
|
-
"SELECT * FROM project_utilities ORDER BY updated_at DESC LIMIT ?"
|
|
750
|
-
).all(limit) as any[];
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
// Buscar por diretorio (prioridade) e scope (fallback)
|
|
754
|
-
const conditions: string[] = [];
|
|
755
|
-
const params: any[] = [];
|
|
756
|
-
|
|
757
|
-
for (const dir of dirs) {
|
|
758
|
-
const normalized = dir.replace(/\\/g, "/");
|
|
759
|
-
conditions.push("REPLACE(file_path, '\\', '/') LIKE ?");
|
|
760
|
-
params.push(`${normalized}%`);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
if (scope) {
|
|
764
|
-
conditions.push("scope = ?");
|
|
765
|
-
params.push(scope);
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
params.push(limit);
|
|
769
|
-
const where = conditions.length > 0 ? `WHERE (${conditions.join(" OR ")})` : "";
|
|
770
|
-
return db.query(
|
|
771
|
-
`SELECT * FROM project_utilities ${where} ORDER BY updated_at DESC LIMIT ?`
|
|
772
|
-
).all(...params) as any[];
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
export function findDuplicateUtilities(
|
|
776
|
-
utilityName: string,
|
|
777
|
-
excludeFile?: string
|
|
778
|
-
): any[] {
|
|
779
|
-
const db = getDb();
|
|
780
|
-
if (excludeFile) {
|
|
781
|
-
return db.query(
|
|
782
|
-
"SELECT * FROM project_utilities WHERE utility_name = ? AND file_path != ?"
|
|
783
|
-
).all(utilityName, excludeFile) as any[];
|
|
784
|
-
}
|
|
785
|
-
return db.query(
|
|
786
|
-
"SELECT * FROM project_utilities WHERE utility_name = ?"
|
|
787
|
-
).all(utilityName) as any[];
|
|
788
|
-
}
|
|
1
|
+
import { getDb } from "./connection";
|
|
2
|
+
|
|
3
|
+
export function initSchema(): void {
|
|
4
|
+
const db = getDb();
|
|
5
|
+
|
|
6
|
+
db.exec(`
|
|
7
|
+
-- 1. Feature sendo desenvolvida
|
|
8
|
+
CREATE TABLE IF NOT EXISTS specs (
|
|
9
|
+
id TEXT PRIMARY KEY,
|
|
10
|
+
name TEXT NOT NULL,
|
|
11
|
+
phase TEXT NOT NULL DEFAULT 'planning',
|
|
12
|
+
approved_at TEXT,
|
|
13
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
14
|
+
updated_at TEXT
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
-- 2. Contexto compartilhado (o coracao do sistema)
|
|
18
|
+
CREATE TABLE IF NOT EXISTS context (
|
|
19
|
+
spec_id TEXT PRIMARY KEY REFERENCES specs(id),
|
|
20
|
+
objective TEXT NOT NULL,
|
|
21
|
+
approach TEXT,
|
|
22
|
+
constraints TEXT,
|
|
23
|
+
patterns TEXT,
|
|
24
|
+
current_task INTEGER,
|
|
25
|
+
total_tasks INTEGER,
|
|
26
|
+
last_checkpoint TEXT,
|
|
27
|
+
updated_at TEXT
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
-- 3. Tarefas com dependencias (para paralelizacao)
|
|
31
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
32
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
33
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
34
|
+
number INTEGER NOT NULL,
|
|
35
|
+
name TEXT NOT NULL,
|
|
36
|
+
depends_on TEXT,
|
|
37
|
+
can_parallel INTEGER DEFAULT 1,
|
|
38
|
+
agent TEXT,
|
|
39
|
+
files TEXT,
|
|
40
|
+
status TEXT DEFAULT 'pending',
|
|
41
|
+
checkpoint TEXT,
|
|
42
|
+
completed_at TEXT,
|
|
43
|
+
UNIQUE(spec_id, number)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- 4. Decisoes (registro critico)
|
|
47
|
+
CREATE TABLE IF NOT EXISTS decisions (
|
|
48
|
+
id TEXT PRIMARY KEY,
|
|
49
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
50
|
+
task_ref INTEGER,
|
|
51
|
+
title TEXT NOT NULL,
|
|
52
|
+
decision TEXT NOT NULL,
|
|
53
|
+
rationale TEXT,
|
|
54
|
+
status TEXT DEFAULT 'active',
|
|
55
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
-- 5. Artefatos
|
|
59
|
+
CREATE TABLE IF NOT EXISTS artifacts (
|
|
60
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
61
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
62
|
+
task_ref INTEGER NOT NULL,
|
|
63
|
+
path TEXT NOT NULL,
|
|
64
|
+
action TEXT NOT NULL,
|
|
65
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
66
|
+
UNIQUE(spec_id, path)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
-- 6. Review (fase REV)
|
|
70
|
+
CREATE TABLE IF NOT EXISTS review (
|
|
71
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
72
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
73
|
+
planned_vs_done TEXT,
|
|
74
|
+
deviations TEXT,
|
|
75
|
+
pattern_violations TEXT,
|
|
76
|
+
status TEXT DEFAULT 'pending',
|
|
77
|
+
resolution TEXT,
|
|
78
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
-- 7. Snapshots (recovery)
|
|
82
|
+
CREATE TABLE IF NOT EXISTS snapshots (
|
|
83
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
84
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
85
|
+
data TEXT NOT NULL,
|
|
86
|
+
trigger TEXT NOT NULL,
|
|
87
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
-- 8. Projeto (informacoes detectadas no discover)
|
|
91
|
+
CREATE TABLE IF NOT EXISTS project (
|
|
92
|
+
id TEXT PRIMARY KEY DEFAULT 'default',
|
|
93
|
+
name TEXT,
|
|
94
|
+
stack TEXT NOT NULL,
|
|
95
|
+
discovered_at TEXT,
|
|
96
|
+
updated_at TEXT
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
-- 9. Standards do projeto
|
|
100
|
+
CREATE TABLE IF NOT EXISTS standards (
|
|
101
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
102
|
+
category TEXT NOT NULL,
|
|
103
|
+
scope TEXT NOT NULL,
|
|
104
|
+
rule TEXT NOT NULL,
|
|
105
|
+
examples TEXT,
|
|
106
|
+
anti_examples TEXT,
|
|
107
|
+
enforcement TEXT DEFAULT 'required',
|
|
108
|
+
source TEXT,
|
|
109
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
-- 10. Knowledge broadcast (compartilhamento em tempo real)
|
|
113
|
+
CREATE TABLE IF NOT EXISTS knowledge (
|
|
114
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
115
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
116
|
+
task_origin INTEGER NOT NULL,
|
|
117
|
+
category TEXT NOT NULL,
|
|
118
|
+
content TEXT NOT NULL,
|
|
119
|
+
severity TEXT DEFAULT 'info',
|
|
120
|
+
broadcast_to TEXT DEFAULT 'all',
|
|
121
|
+
acknowledged_by TEXT,
|
|
122
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
-- 11. Gate bypass log (auditoria de bypasses)
|
|
126
|
+
CREATE TABLE IF NOT EXISTS gate_bypasses (
|
|
127
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
128
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
129
|
+
task_id INTEGER NOT NULL,
|
|
130
|
+
gate_name TEXT NOT NULL,
|
|
131
|
+
reason TEXT,
|
|
132
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
-- 12. Product context (PRD/contexto de produto)
|
|
136
|
+
CREATE TABLE IF NOT EXISTS product_context (
|
|
137
|
+
id TEXT PRIMARY KEY DEFAULT 'default',
|
|
138
|
+
name TEXT NOT NULL,
|
|
139
|
+
problem TEXT NOT NULL,
|
|
140
|
+
solution TEXT,
|
|
141
|
+
target_users TEXT,
|
|
142
|
+
value_proposition TEXT,
|
|
143
|
+
success_metrics TEXT,
|
|
144
|
+
out_of_scope TEXT,
|
|
145
|
+
constraints TEXT,
|
|
146
|
+
source TEXT DEFAULT 'guide',
|
|
147
|
+
discovered_at TEXT,
|
|
148
|
+
updated_at TEXT
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
-- 13. Product goals (objetivos do produto)
|
|
152
|
+
CREATE TABLE IF NOT EXISTS product_goals (
|
|
153
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
154
|
+
product_id TEXT NOT NULL DEFAULT 'default' REFERENCES product_context(id),
|
|
155
|
+
category TEXT NOT NULL,
|
|
156
|
+
goal TEXT NOT NULL,
|
|
157
|
+
priority TEXT DEFAULT 'medium',
|
|
158
|
+
status TEXT DEFAULT 'active',
|
|
159
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
-- 14. Product features (features core do produto)
|
|
163
|
+
CREATE TABLE IF NOT EXISTS product_features (
|
|
164
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
165
|
+
product_id TEXT NOT NULL DEFAULT 'default' REFERENCES product_context(id),
|
|
166
|
+
name TEXT NOT NULL,
|
|
167
|
+
description TEXT,
|
|
168
|
+
priority TEXT DEFAULT 'medium',
|
|
169
|
+
status TEXT DEFAULT 'planned',
|
|
170
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
-- 15. Library contexts (contexto atualizado por biblioteca)
|
|
174
|
+
CREATE TABLE IF NOT EXISTS lib_contexts (
|
|
175
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
176
|
+
lib_name TEXT NOT NULL UNIQUE,
|
|
177
|
+
version TEXT NOT NULL,
|
|
178
|
+
context_file TEXT NOT NULL,
|
|
179
|
+
source_url TEXT,
|
|
180
|
+
researched_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
181
|
+
updated_at TEXT
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
-- 16. Agent lib mappings (quais libs cada agente carrega)
|
|
185
|
+
CREATE TABLE IF NOT EXISTS agent_lib_mappings (
|
|
186
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
187
|
+
agent_type TEXT NOT NULL,
|
|
188
|
+
lib_name TEXT NOT NULL,
|
|
189
|
+
priority INTEGER DEFAULT 0,
|
|
190
|
+
UNIQUE(agent_type, lib_name)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
-- 17. Implementation patterns (padroes extraidos do codigo - v7.4)
|
|
194
|
+
CREATE TABLE IF NOT EXISTS implementation_patterns (
|
|
195
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
196
|
+
|
|
197
|
+
-- Identificacao
|
|
198
|
+
category TEXT NOT NULL, -- component, hook, service, route, schema, test, action
|
|
199
|
+
name TEXT NOT NULL UNIQUE, -- ex: "page-component", "data-hook", "api-route"
|
|
200
|
+
|
|
201
|
+
-- Contexto
|
|
202
|
+
scope TEXT NOT NULL, -- frontend, backend, database, testing
|
|
203
|
+
applies_to TEXT NOT NULL, -- glob pattern: "app/**/page.tsx", "src/hooks/*.ts"
|
|
204
|
+
|
|
205
|
+
-- O Padrao Extraido
|
|
206
|
+
structure TEXT NOT NULL, -- JSON com estrutura comum (imports, exports, patterns, conventions)
|
|
207
|
+
template TEXT NOT NULL, -- Template de codigo com placeholders
|
|
208
|
+
examples TEXT NOT NULL, -- JSON array de arquivos que seguem este padrao
|
|
209
|
+
|
|
210
|
+
-- Anti-patterns identificados
|
|
211
|
+
anti_patterns TEXT, -- JSON array de anti-patterns encontrados
|
|
212
|
+
|
|
213
|
+
-- Metadados
|
|
214
|
+
confidence REAL DEFAULT 0.8, -- 0-1, baseado em quantos arquivos seguem
|
|
215
|
+
extracted_from INTEGER, -- Quantos arquivos foram analisados
|
|
216
|
+
|
|
217
|
+
-- Auditoria
|
|
218
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
219
|
+
updated_at TEXT
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
-- 18. Knowledge Graph (v8.0 - Relacoes entre entidades)
|
|
223
|
+
CREATE TABLE IF NOT EXISTS knowledge_graph (
|
|
224
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
225
|
+
spec_id TEXT REFERENCES specs(id),
|
|
226
|
+
|
|
227
|
+
-- No de origem
|
|
228
|
+
source_type TEXT NOT NULL, -- file, decision, pattern, task, artifact
|
|
229
|
+
source_id TEXT NOT NULL,
|
|
230
|
+
|
|
231
|
+
-- No de destino
|
|
232
|
+
target_type TEXT NOT NULL,
|
|
233
|
+
target_id TEXT NOT NULL,
|
|
234
|
+
|
|
235
|
+
-- Relacao
|
|
236
|
+
relation TEXT NOT NULL, -- uses, implements, depends_on, modifies, contradicts, extracted_from
|
|
237
|
+
|
|
238
|
+
-- Metadados
|
|
239
|
+
strength REAL DEFAULT 1.0, -- 0-1, peso da relacao
|
|
240
|
+
metadata TEXT, -- JSON com informacoes adicionais
|
|
241
|
+
|
|
242
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
-- 19. Reasoning Log (v8.0 - Historico de raciocinio)
|
|
246
|
+
CREATE TABLE IF NOT EXISTS reasoning_log (
|
|
247
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
248
|
+
spec_id TEXT REFERENCES specs(id),
|
|
249
|
+
task_id INTEGER REFERENCES tasks(id),
|
|
250
|
+
|
|
251
|
+
-- O raciocinio
|
|
252
|
+
category TEXT NOT NULL, -- decision, discovery, error, success, challenge, recommendation
|
|
253
|
+
thought TEXT NOT NULL, -- "Escolhi X porque Y"
|
|
254
|
+
|
|
255
|
+
-- Contexto
|
|
256
|
+
related_files TEXT, -- JSON array de arquivos
|
|
257
|
+
related_decisions TEXT, -- JSON array de decision IDs
|
|
258
|
+
related_patterns TEXT, -- JSON array de pattern names
|
|
259
|
+
|
|
260
|
+
-- Importancia
|
|
261
|
+
importance TEXT DEFAULT 'normal', -- critical, high, normal, low
|
|
262
|
+
|
|
263
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
-- 20. Session Summaries (v8.0 - Resumos de sessao para continuidade)
|
|
267
|
+
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
268
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
269
|
+
spec_id TEXT NOT NULL REFERENCES specs(id),
|
|
270
|
+
|
|
271
|
+
-- Periodo
|
|
272
|
+
start_time TEXT NOT NULL,
|
|
273
|
+
end_time TEXT NOT NULL,
|
|
274
|
+
|
|
275
|
+
-- Conteudo
|
|
276
|
+
summary TEXT NOT NULL, -- O que foi feito
|
|
277
|
+
decisions TEXT, -- JSON array de decisoes tomadas
|
|
278
|
+
blockers TEXT, -- JSON array de problemas encontrados
|
|
279
|
+
next_steps TEXT, -- JSON array de recomendacoes
|
|
280
|
+
|
|
281
|
+
-- Estatisticas
|
|
282
|
+
tasks_completed INTEGER DEFAULT 0,
|
|
283
|
+
files_created INTEGER DEFAULT 0,
|
|
284
|
+
files_modified INTEGER DEFAULT 0,
|
|
285
|
+
|
|
286
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
-- 21. Architectural Analyses (v8.1 - migrado de architect.ts para schema central)
|
|
290
|
+
CREATE TABLE IF NOT EXISTS architectural_analyses (
|
|
291
|
+
id TEXT PRIMARY KEY,
|
|
292
|
+
name TEXT NOT NULL,
|
|
293
|
+
description TEXT NOT NULL,
|
|
294
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
295
|
+
|
|
296
|
+
-- Conteudo JSON
|
|
297
|
+
context TEXT,
|
|
298
|
+
current_architecture TEXT,
|
|
299
|
+
approach TEXT,
|
|
300
|
+
chosen_alternative TEXT,
|
|
301
|
+
diagrams TEXT, -- JSON array
|
|
302
|
+
baby_steps TEXT, -- JSON array
|
|
303
|
+
risks TEXT, -- JSON array
|
|
304
|
+
alternatives TEXT, -- JSON array
|
|
305
|
+
decisions TEXT, -- JSON array
|
|
306
|
+
|
|
307
|
+
-- Arquivo gerado
|
|
308
|
+
file_path TEXT,
|
|
309
|
+
|
|
310
|
+
-- Timestamps
|
|
311
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
312
|
+
updated_at TEXT,
|
|
313
|
+
approved_at TEXT
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
-- 22. Project Utilities (v8.5 - DRY enforcement utility map)
|
|
317
|
+
CREATE TABLE IF NOT EXISTS project_utilities (
|
|
318
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
319
|
+
file_path TEXT NOT NULL,
|
|
320
|
+
utility_name TEXT NOT NULL,
|
|
321
|
+
utility_type TEXT NOT NULL,
|
|
322
|
+
scope TEXT NOT NULL,
|
|
323
|
+
signature TEXT,
|
|
324
|
+
description TEXT,
|
|
325
|
+
spec_id TEXT,
|
|
326
|
+
task_ref INTEGER,
|
|
327
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
328
|
+
updated_at TEXT,
|
|
329
|
+
UNIQUE(file_path, utility_name)
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
-- Indices para performance
|
|
333
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_spec ON tasks(spec_id);
|
|
334
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
335
|
+
CREATE INDEX IF NOT EXISTS idx_decisions_spec ON decisions(spec_id);
|
|
336
|
+
CREATE INDEX IF NOT EXISTS idx_artifacts_spec ON artifacts(spec_id);
|
|
337
|
+
CREATE INDEX IF NOT EXISTS idx_snapshots_spec ON snapshots(spec_id);
|
|
338
|
+
CREATE INDEX IF NOT EXISTS idx_standards_category ON standards(category);
|
|
339
|
+
CREATE INDEX IF NOT EXISTS idx_standards_scope ON standards(scope);
|
|
340
|
+
CREATE INDEX IF NOT EXISTS idx_knowledge_spec ON knowledge(spec_id);
|
|
341
|
+
CREATE INDEX IF NOT EXISTS idx_knowledge_category ON knowledge(category);
|
|
342
|
+
CREATE INDEX IF NOT EXISTS idx_knowledge_severity ON knowledge(severity);
|
|
343
|
+
CREATE INDEX IF NOT EXISTS idx_gate_bypasses_spec ON gate_bypasses(spec_id);
|
|
344
|
+
CREATE INDEX IF NOT EXISTS idx_product_goals_product ON product_goals(product_id);
|
|
345
|
+
CREATE INDEX IF NOT EXISTS idx_product_goals_category ON product_goals(category);
|
|
346
|
+
CREATE INDEX IF NOT EXISTS idx_product_features_product ON product_features(product_id);
|
|
347
|
+
CREATE INDEX IF NOT EXISTS idx_product_features_priority ON product_features(priority);
|
|
348
|
+
CREATE INDEX IF NOT EXISTS idx_lib_contexts_lib ON lib_contexts(lib_name);
|
|
349
|
+
CREATE INDEX IF NOT EXISTS idx_agent_lib_mappings_agent ON agent_lib_mappings(agent_type);
|
|
350
|
+
CREATE INDEX IF NOT EXISTS idx_impl_patterns_category ON implementation_patterns(category);
|
|
351
|
+
CREATE INDEX IF NOT EXISTS idx_impl_patterns_scope ON implementation_patterns(scope);
|
|
352
|
+
CREATE INDEX IF NOT EXISTS idx_impl_patterns_name ON implementation_patterns(name);
|
|
353
|
+
|
|
354
|
+
-- v8.0: Indices para Knowledge Graph
|
|
355
|
+
CREATE INDEX IF NOT EXISTS idx_kg_source ON knowledge_graph(source_type, source_id);
|
|
356
|
+
CREATE INDEX IF NOT EXISTS idx_kg_target ON knowledge_graph(target_type, target_id);
|
|
357
|
+
CREATE INDEX IF NOT EXISTS idx_kg_relation ON knowledge_graph(relation);
|
|
358
|
+
CREATE INDEX IF NOT EXISTS idx_kg_spec ON knowledge_graph(spec_id);
|
|
359
|
+
|
|
360
|
+
-- v8.0: Indices para Reasoning Log
|
|
361
|
+
CREATE INDEX IF NOT EXISTS idx_reasoning_spec ON reasoning_log(spec_id);
|
|
362
|
+
CREATE INDEX IF NOT EXISTS idx_reasoning_task ON reasoning_log(task_id);
|
|
363
|
+
CREATE INDEX IF NOT EXISTS idx_reasoning_category ON reasoning_log(category);
|
|
364
|
+
CREATE INDEX IF NOT EXISTS idx_reasoning_importance ON reasoning_log(importance);
|
|
365
|
+
|
|
366
|
+
-- v8.0: Indices para Session Summaries
|
|
367
|
+
CREATE INDEX IF NOT EXISTS idx_session_spec ON session_summaries(spec_id);
|
|
368
|
+
CREATE INDEX IF NOT EXISTS idx_session_time ON session_summaries(end_time);
|
|
369
|
+
|
|
370
|
+
-- v8.1: Indices para Architectural Analyses
|
|
371
|
+
CREATE INDEX IF NOT EXISTS idx_arch_status ON architectural_analyses(status);
|
|
372
|
+
CREATE INDEX IF NOT EXISTS idx_arch_created ON architectural_analyses(created_at);
|
|
373
|
+
|
|
374
|
+
-- v8.5: Indices para Project Utilities
|
|
375
|
+
CREATE INDEX IF NOT EXISTS idx_utils_scope ON project_utilities(scope);
|
|
376
|
+
CREATE INDEX IF NOT EXISTS idx_utils_name ON project_utilities(utility_name);
|
|
377
|
+
CREATE INDEX IF NOT EXISTS idx_utils_file ON project_utilities(file_path);
|
|
378
|
+
`);
|
|
379
|
+
|
|
380
|
+
// v8.4: Migracao - adicionar analysis_id na tabela specs
|
|
381
|
+
try {
|
|
382
|
+
db.exec(`ALTER TABLE specs ADD COLUMN analysis_id TEXT`);
|
|
383
|
+
} catch {
|
|
384
|
+
// Coluna ja existe - ignorar
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function getPatternsByScope(scope: string): any[] {
|
|
389
|
+
const db = getDb();
|
|
390
|
+
return db.query(
|
|
391
|
+
"SELECT * FROM implementation_patterns WHERE scope = ? OR scope = 'all' ORDER BY category, name"
|
|
392
|
+
).all(scope) as any[];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function getPatternsForFiles(files: string[]): any[] {
|
|
396
|
+
const db = getDb();
|
|
397
|
+
const patterns = db.query("SELECT * FROM implementation_patterns").all() as any[];
|
|
398
|
+
|
|
399
|
+
// Filtrar patterns que correspondem aos arquivos da task
|
|
400
|
+
return patterns.filter(pattern => {
|
|
401
|
+
const glob = pattern.applies_to;
|
|
402
|
+
return files.some(file => {
|
|
403
|
+
// Simplificado: verificar se o arquivo corresponde ao glob pattern
|
|
404
|
+
// Ex: "app/**/page.tsx" deve corresponder a "app/dashboard/page.tsx"
|
|
405
|
+
const regexPattern = glob
|
|
406
|
+
.replace(/\*\*/g, '.*')
|
|
407
|
+
.replace(/\*/g, '[^/]*')
|
|
408
|
+
.replace(/\//g, '\\/');
|
|
409
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
410
|
+
return regex.test(file);
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ═══════════════════════════════════════════════════════════════
|
|
416
|
+
// v8.0: Knowledge Graph Helpers
|
|
417
|
+
// ═══════════════════════════════════════════════════════════════
|
|
418
|
+
|
|
419
|
+
export interface GraphRelation {
|
|
420
|
+
sourceType: string;
|
|
421
|
+
sourceId: string;
|
|
422
|
+
targetType: string;
|
|
423
|
+
targetId: string;
|
|
424
|
+
relation: string;
|
|
425
|
+
strength?: number;
|
|
426
|
+
metadata?: Record<string, any>;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export function addGraphRelation(specId: string | null, relation: GraphRelation): void {
|
|
430
|
+
const db = getDb();
|
|
431
|
+
const now = new Date().toISOString();
|
|
432
|
+
|
|
433
|
+
db.run(
|
|
434
|
+
`INSERT INTO knowledge_graph (spec_id, source_type, source_id, target_type, target_id, relation, strength, metadata, created_at)
|
|
435
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
436
|
+
[
|
|
437
|
+
specId,
|
|
438
|
+
relation.sourceType,
|
|
439
|
+
relation.sourceId,
|
|
440
|
+
relation.targetType,
|
|
441
|
+
relation.targetId,
|
|
442
|
+
relation.relation,
|
|
443
|
+
relation.strength || 1.0,
|
|
444
|
+
relation.metadata ? JSON.stringify(relation.metadata) : null,
|
|
445
|
+
now,
|
|
446
|
+
]
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function getRelatedDecisions(fileOrPattern: string, type: "file" | "pattern"): any[] {
|
|
451
|
+
const db = getDb();
|
|
452
|
+
|
|
453
|
+
return db.query(`
|
|
454
|
+
SELECT d.* FROM decisions d
|
|
455
|
+
JOIN knowledge_graph kg ON kg.source_id = d.id AND kg.source_type = 'decision'
|
|
456
|
+
WHERE kg.target_type = ? AND kg.target_id = ?
|
|
457
|
+
AND kg.relation IN ('implements', 'depends_on', 'uses')
|
|
458
|
+
`).all(type, fileOrPattern) as any[];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function getRelatedFiles(decisionOrPattern: string, type: "decision" | "pattern"): string[] {
|
|
462
|
+
const db = getDb();
|
|
463
|
+
|
|
464
|
+
const results = db.query(`
|
|
465
|
+
SELECT kg.target_id as file FROM knowledge_graph kg
|
|
466
|
+
WHERE kg.source_type = ? AND kg.source_id = ?
|
|
467
|
+
AND kg.target_type = 'file'
|
|
468
|
+
AND kg.relation IN ('implements', 'modifies', 'creates')
|
|
469
|
+
`).all(type, decisionOrPattern) as any[];
|
|
470
|
+
|
|
471
|
+
return results.map(r => r.file);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export function findContradictions(specId: string): Array<{ decision1: string; decision2: string; createdAt: string }> {
|
|
475
|
+
const db = getDb();
|
|
476
|
+
|
|
477
|
+
return db.query(`
|
|
478
|
+
SELECT
|
|
479
|
+
d1.title as decision1,
|
|
480
|
+
d2.title as decision2,
|
|
481
|
+
kg.created_at as createdAt
|
|
482
|
+
FROM knowledge_graph kg
|
|
483
|
+
JOIN decisions d1 ON kg.source_id = d1.id
|
|
484
|
+
JOIN decisions d2 ON kg.target_id = d2.id
|
|
485
|
+
WHERE kg.relation = 'contradicts'
|
|
486
|
+
AND kg.spec_id = ?
|
|
487
|
+
`).all(specId) as any[];
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ═══════════════════════════════════════════════════════════════
|
|
491
|
+
// v8.0: Reasoning Log Helpers
|
|
492
|
+
// ═══════════════════════════════════════════════════════════════
|
|
493
|
+
|
|
494
|
+
export interface ReasoningEntry {
|
|
495
|
+
category: "decision" | "discovery" | "error" | "success" | "challenge" | "recommendation";
|
|
496
|
+
thought: string;
|
|
497
|
+
relatedFiles?: string[];
|
|
498
|
+
relatedDecisions?: string[];
|
|
499
|
+
relatedPatterns?: string[];
|
|
500
|
+
importance?: "critical" | "high" | "normal" | "low";
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export function addReasoning(specId: string, taskId: number | null, entry: ReasoningEntry): void {
|
|
504
|
+
const db = getDb();
|
|
505
|
+
const now = new Date().toISOString();
|
|
506
|
+
|
|
507
|
+
db.run(
|
|
508
|
+
`INSERT INTO reasoning_log (spec_id, task_id, category, thought, related_files, related_decisions, related_patterns, importance, created_at)
|
|
509
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
510
|
+
[
|
|
511
|
+
specId,
|
|
512
|
+
taskId,
|
|
513
|
+
entry.category,
|
|
514
|
+
entry.thought,
|
|
515
|
+
entry.relatedFiles ? JSON.stringify(entry.relatedFiles) : null,
|
|
516
|
+
entry.relatedDecisions ? JSON.stringify(entry.relatedDecisions) : null,
|
|
517
|
+
entry.relatedPatterns ? JSON.stringify(entry.relatedPatterns) : null,
|
|
518
|
+
entry.importance || "normal",
|
|
519
|
+
now,
|
|
520
|
+
]
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function getRecentReasoning(specId: string, limit: number = 20): any[] {
|
|
525
|
+
const db = getDb();
|
|
526
|
+
|
|
527
|
+
return db.query(`
|
|
528
|
+
SELECT * FROM reasoning_log
|
|
529
|
+
WHERE spec_id = ?
|
|
530
|
+
ORDER BY created_at DESC
|
|
531
|
+
LIMIT ?
|
|
532
|
+
`).all(specId, limit) as any[];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// ═══════════════════════════════════════════════════════════════
|
|
536
|
+
// v8.0: Session Summary Helpers
|
|
537
|
+
// ═══════════════════════════════════════════════════════════════
|
|
538
|
+
|
|
539
|
+
export interface SessionSummaryData {
|
|
540
|
+
startTime: string;
|
|
541
|
+
endTime: string;
|
|
542
|
+
summary: string;
|
|
543
|
+
decisions?: string[];
|
|
544
|
+
blockers?: string[];
|
|
545
|
+
nextSteps?: string[];
|
|
546
|
+
tasksCompleted?: number;
|
|
547
|
+
filesCreated?: number;
|
|
548
|
+
filesModified?: number;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export function addSessionSummary(specId: string, data: SessionSummaryData): void {
|
|
552
|
+
const db = getDb();
|
|
553
|
+
const now = new Date().toISOString();
|
|
554
|
+
|
|
555
|
+
db.run(
|
|
556
|
+
`INSERT INTO session_summaries (spec_id, start_time, end_time, summary, decisions, blockers, next_steps, tasks_completed, files_created, files_modified, created_at)
|
|
557
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
558
|
+
[
|
|
559
|
+
specId,
|
|
560
|
+
data.startTime,
|
|
561
|
+
data.endTime,
|
|
562
|
+
data.summary,
|
|
563
|
+
data.decisions ? JSON.stringify(data.decisions) : null,
|
|
564
|
+
data.blockers ? JSON.stringify(data.blockers) : null,
|
|
565
|
+
data.nextSteps ? JSON.stringify(data.nextSteps) : null,
|
|
566
|
+
data.tasksCompleted || 0,
|
|
567
|
+
data.filesCreated || 0,
|
|
568
|
+
data.filesModified || 0,
|
|
569
|
+
now,
|
|
570
|
+
]
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export function getLastSessionSummary(specId: string): any {
|
|
575
|
+
const db = getDb();
|
|
576
|
+
|
|
577
|
+
return db.query(`
|
|
578
|
+
SELECT * FROM session_summaries
|
|
579
|
+
WHERE spec_id = ?
|
|
580
|
+
ORDER BY created_at DESC
|
|
581
|
+
LIMIT 1
|
|
582
|
+
`).get(specId);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// v8.3: Retorna ultimas N sessoes para contexto composto
|
|
586
|
+
export function getSessionSummaries(specId: string, limit: number = 5): any[] {
|
|
587
|
+
const db = getDb();
|
|
588
|
+
|
|
589
|
+
return db.query(`
|
|
590
|
+
SELECT * FROM session_summaries
|
|
591
|
+
WHERE spec_id = ?
|
|
592
|
+
ORDER BY created_at DESC
|
|
593
|
+
LIMIT ?
|
|
594
|
+
`).all(specId, limit) as any[];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// v8.4: Busca analise arquitetural associada a um spec
|
|
598
|
+
// Prioridade: analysis_id (link explicito) > nome exato > LIKE parcial
|
|
599
|
+
export function getArchitecturalAnalysisForSpec(specName: string, specId?: string): any {
|
|
600
|
+
const db = getDb();
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
// 0. Link explicito via analysis_id na tabela specs
|
|
604
|
+
if (specId) {
|
|
605
|
+
const spec = db.query("SELECT analysis_id FROM specs WHERE id = ?").get(specId) as any;
|
|
606
|
+
if (spec?.analysis_id) {
|
|
607
|
+
const analysis = db.query(
|
|
608
|
+
"SELECT * FROM architectural_analyses WHERE id = ? AND status IN ('approved', 'implemented')"
|
|
609
|
+
).get(spec.analysis_id) as any;
|
|
610
|
+
if (analysis) return analysis;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// 1. Match exato por nome
|
|
615
|
+
let analysis = db.query(
|
|
616
|
+
"SELECT * FROM architectural_analyses WHERE name = ? AND status IN ('approved', 'implemented') ORDER BY approved_at DESC LIMIT 1"
|
|
617
|
+
).get(specName) as any;
|
|
618
|
+
|
|
619
|
+
if (analysis) return analysis;
|
|
620
|
+
|
|
621
|
+
// 2. Match parcial (nome da spec contido no nome da analise ou vice-versa)
|
|
622
|
+
analysis = db.query(
|
|
623
|
+
"SELECT * FROM architectural_analyses WHERE (name LIKE ? OR ? LIKE '%' || name || '%') AND status IN ('approved', 'implemented') ORDER BY approved_at DESC LIMIT 1"
|
|
624
|
+
).get(`%${specName}%`, specName) as any;
|
|
625
|
+
|
|
626
|
+
return analysis || null;
|
|
627
|
+
} catch {
|
|
628
|
+
// Tabela pode nao existir se architect nunca foi usado
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// ═══════════════════════════════════════════════════════════════
|
|
634
|
+
// v8.5: Project Utilities Helpers (DRY enforcement)
|
|
635
|
+
// ═══════════════════════════════════════════════════════════════
|
|
636
|
+
|
|
637
|
+
export interface ProjectUtility {
|
|
638
|
+
filePath: string;
|
|
639
|
+
utilityName: string;
|
|
640
|
+
utilityType: string;
|
|
641
|
+
scope: string;
|
|
642
|
+
signature?: string;
|
|
643
|
+
description?: string;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export function upsertUtility(
|
|
647
|
+
utility: ProjectUtility,
|
|
648
|
+
specId?: string,
|
|
649
|
+
taskRef?: number
|
|
650
|
+
): void {
|
|
651
|
+
const db = getDb();
|
|
652
|
+
const now = new Date().toISOString();
|
|
653
|
+
db.run(
|
|
654
|
+
`INSERT INTO project_utilities (file_path, utility_name, utility_type, scope, signature, description, spec_id, task_ref, created_at, updated_at)
|
|
655
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
656
|
+
ON CONFLICT(file_path, utility_name) DO UPDATE SET
|
|
657
|
+
utility_type = excluded.utility_type,
|
|
658
|
+
scope = excluded.scope,
|
|
659
|
+
signature = COALESCE(excluded.signature, project_utilities.signature),
|
|
660
|
+
description = COALESCE(excluded.description, project_utilities.description),
|
|
661
|
+
updated_at = excluded.updated_at`,
|
|
662
|
+
[
|
|
663
|
+
utility.filePath, utility.utilityName, utility.utilityType, utility.scope,
|
|
664
|
+
utility.signature || null, utility.description || null,
|
|
665
|
+
specId || null, taskRef || null, now, now,
|
|
666
|
+
]
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export function getUtilitiesForContext(
|
|
671
|
+
dirs: string[],
|
|
672
|
+
scope?: string,
|
|
673
|
+
limit: number = 15
|
|
674
|
+
): any[] {
|
|
675
|
+
const db = getDb();
|
|
676
|
+
|
|
677
|
+
// Se nenhum filtro, retornar mais recentes
|
|
678
|
+
if (dirs.length === 0 && !scope) {
|
|
679
|
+
return db.query(
|
|
680
|
+
"SELECT * FROM project_utilities ORDER BY updated_at DESC LIMIT ?"
|
|
681
|
+
).all(limit) as any[];
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Buscar por diretorio (prioridade) e scope (fallback)
|
|
685
|
+
const conditions: string[] = [];
|
|
686
|
+
const params: any[] = [];
|
|
687
|
+
|
|
688
|
+
for (const dir of dirs) {
|
|
689
|
+
const normalized = dir.replace(/\\/g, "/");
|
|
690
|
+
conditions.push("REPLACE(file_path, '\\', '/') LIKE ?");
|
|
691
|
+
params.push(`${normalized}%`);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (scope) {
|
|
695
|
+
conditions.push("scope = ?");
|
|
696
|
+
params.push(scope);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
params.push(limit);
|
|
700
|
+
const where = conditions.length > 0 ? `WHERE (${conditions.join(" OR ")})` : "";
|
|
701
|
+
return db.query(
|
|
702
|
+
`SELECT * FROM project_utilities ${where} ORDER BY updated_at DESC LIMIT ?`
|
|
703
|
+
).all(...params) as any[];
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export function findDuplicateUtilities(
|
|
707
|
+
utilityName: string,
|
|
708
|
+
excludeFile?: string
|
|
709
|
+
): any[] {
|
|
710
|
+
const db = getDb();
|
|
711
|
+
if (excludeFile) {
|
|
712
|
+
return db.query(
|
|
713
|
+
"SELECT * FROM project_utilities WHERE utility_name = ? AND file_path != ?"
|
|
714
|
+
).all(utilityName, excludeFile) as any[];
|
|
715
|
+
}
|
|
716
|
+
return db.query(
|
|
717
|
+
"SELECT * FROM project_utilities WHERE utility_name = ?"
|
|
718
|
+
).all(utilityName) as any[];
|
|
719
|
+
}
|