@massu/core 1.10.8 → 1.12.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/CHANGELOG.md +1303 -0
- package/dist/adapter.js +6 -4
- package/dist/cli.js +517 -397
- package/dist/detect/adapters/.bundle-shasums.json +4 -7
- package/dist/detect/adapters/rails.js +6 -4
- package/dist/detect/adapters/spring.js +6 -4
- package/dist/detect/adapters/tree-sitter-loader.js +6 -4
- package/dist/hooks/auto-learning-pipeline.js +24 -1
- package/dist/hooks/classify-failure.js +32 -3
- package/dist/hooks/cost-tracker.js +24 -0
- package/dist/hooks/fix-detector.js +97 -1
- package/dist/hooks/incident-pipeline.js +30 -1
- package/dist/hooks/intent-suggester.js +6 -3
- package/dist/hooks/post-edit-context.js +24 -1
- package/dist/hooks/post-tool-use.js +66 -18
- package/dist/hooks/pre-compact.js +27 -2
- package/dist/hooks/pre-delete-check.js +48 -22
- package/dist/hooks/pre-tool-use-gate.js +962 -0
- package/dist/hooks/quality-event.js +24 -0
- package/dist/hooks/rule-enforcement-pipeline.js +24 -1
- package/dist/hooks/security-gate.js +29 -16
- package/dist/hooks/session-end.js +24 -0
- package/dist/hooks/session-start.js +8710 -8460
- package/dist/hooks/user-prompt.js +24 -0
- package/package.json +15 -18
- package/commands/README.md +0 -134
- package/src/adapter.ts +0 -121
- package/src/adr-generator.ts +0 -292
- package/src/analytics.ts +0 -373
- package/src/audit-trail.ts +0 -450
- package/src/backfill-sessions.ts +0 -182
- package/src/changelog-generator.ts +0 -178
- package/src/cli.ts +0 -246
- package/src/cloud-sync.ts +0 -234
- package/src/commands/adapters.ts +0 -824
- package/src/commands/changelog.ts +0 -165
- package/src/commands/config-check-drift.ts +0 -133
- package/src/commands/config-refresh.ts +0 -396
- package/src/commands/config-upgrade.ts +0 -127
- package/src/commands/doctor.ts +0 -485
- package/src/commands/hook-runner.ts +0 -145
- package/src/commands/init.ts +0 -1823
- package/src/commands/install-commands.ts +0 -692
- package/src/commands/install-hooks.ts +0 -27
- package/src/commands/permissions.ts +0 -150
- package/src/commands/refresh-log.ts +0 -37
- package/src/commands/show-template.ts +0 -65
- package/src/commands/template-engine.ts +0 -301
- package/src/commands/watch.ts +0 -430
- package/src/config.ts +0 -765
- package/src/cost-tracker.ts +0 -355
- package/src/db.ts +0 -370
- package/src/dependency-scorer.ts +0 -337
- package/src/detect/adapters/aspnet.ts +0 -4
- package/src/detect/adapters/discover.ts +0 -469
- package/src/detect/adapters/file-sampler.ts +0 -225
- package/src/detect/adapters/go-chi.ts +0 -4
- package/src/detect/adapters/index.ts +0 -51
- package/src/detect/adapters/nextjs-trpc.ts +0 -166
- package/src/detect/adapters/parse-guard.ts +0 -133
- package/src/detect/adapters/phoenix.ts +0 -4
- package/src/detect/adapters/python-django.ts +0 -208
- package/src/detect/adapters/python-fastapi.ts +0 -223
- package/src/detect/adapters/python-flask.ts +0 -235
- package/src/detect/adapters/query-helpers.ts +0 -170
- package/src/detect/adapters/rails.ts +0 -4
- package/src/detect/adapters/runner.ts +0 -284
- package/src/detect/adapters/spring.ts +0 -4
- package/src/detect/adapters/swift-swiftui.ts +0 -171
- package/src/detect/adapters/tree-sitter-loader.ts +0 -517
- package/src/detect/adapters/types.ts +0 -191
- package/src/detect/codebase-introspector.ts +0 -210
- package/src/detect/domain-inferrer.ts +0 -197
- package/src/detect/drift.ts +0 -199
- package/src/detect/framework-detector.ts +0 -307
- package/src/detect/index.ts +0 -209
- package/src/detect/manifest-registry.ts +0 -261
- package/src/detect/migrate.ts +0 -362
- package/src/detect/monorepo-detector.ts +0 -348
- package/src/detect/package-detector.ts +0 -828
- package/src/detect/passthrough.ts +0 -108
- package/src/detect/regex-fallback.ts +0 -449
- package/src/detect/source-dir-detector.ts +0 -297
- package/src/detect/vr-command-map.ts +0 -167
- package/src/docs-map.json +0 -100
- package/src/docs-tools.ts +0 -519
- package/src/domains.ts +0 -182
- package/src/hooks/auto-learning-pipeline.ts +0 -228
- package/src/hooks/classify-failure.ts +0 -259
- package/src/hooks/cost-tracker.ts +0 -66
- package/src/hooks/fix-detector.ts +0 -186
- package/src/hooks/incident-pipeline.ts +0 -190
- package/src/hooks/intent-suggester.ts +0 -131
- package/src/hooks/post-edit-context.ts +0 -91
- package/src/hooks/post-tool-use.ts +0 -413
- package/src/hooks/pre-compact.ts +0 -168
- package/src/hooks/pre-delete-check.ts +0 -243
- package/src/hooks/quality-event.ts +0 -127
- package/src/hooks/rule-enforcement-pipeline.ts +0 -159
- package/src/hooks/security-gate.ts +0 -153
- package/src/hooks/session-end.ts +0 -467
- package/src/hooks/session-start.ts +0 -436
- package/src/hooks/user-prompt.ts +0 -157
- package/src/import-resolver.ts +0 -226
- package/src/knowledge-db.ts +0 -176
- package/src/knowledge-indexer.ts +0 -708
- package/src/knowledge-tools.ts +0 -1414
- package/src/lib/fileLock.ts +0 -203
- package/src/lib/framework-supports.ts +0 -85
- package/src/lib/gitToplevel.ts +0 -22
- package/src/lib/hook-registry.ts +0 -43
- package/src/lib/installLock.ts +0 -66
- package/src/lib/memory-path.ts +0 -49
- package/src/lib/pidLiveness.ts +0 -67
- package/src/lib/settings-local.ts +0 -110
- package/src/lib/sql-table-names.ts +0 -71
- package/src/license.ts +0 -547
- package/src/lsp/auto-detect.ts +0 -98
- package/src/lsp/client.ts +0 -776
- package/src/lsp/enrich.ts +0 -127
- package/src/lsp/types.ts +0 -221
- package/src/memory-db.ts +0 -1614
- package/src/memory-file-ingest.ts +0 -128
- package/src/memory-tools.ts +0 -424
- package/src/middleware-tree.ts +0 -71
- package/src/observability-tools.ts +0 -343
- package/src/observation-extractor.ts +0 -418
- package/src/page-deps.ts +0 -285
- package/src/permissions.ts +0 -422
- package/src/prompt-analyzer.ts +0 -332
- package/src/python/coupling-detector.ts +0 -125
- package/src/python/domain-enforcer.ts +0 -84
- package/src/python/impact-analyzer.ts +0 -96
- package/src/python/import-parser.ts +0 -244
- package/src/python/import-resolver.ts +0 -136
- package/src/python/migration-indexer.ts +0 -116
- package/src/python/migration-parser.ts +0 -332
- package/src/python/model-indexer.ts +0 -71
- package/src/python/model-parser.ts +0 -279
- package/src/python/route-indexer.ts +0 -59
- package/src/python/route-parser.ts +0 -317
- package/src/python-tools.ts +0 -630
- package/src/regression-detector.ts +0 -319
- package/src/rules.ts +0 -57
- package/src/schema-mapper.ts +0 -232
- package/src/security/adapter-origin.ts +0 -130
- package/src/security/adapter-verifier.ts +0 -319
- package/src/security/atomic-write.ts +0 -164
- package/src/security/fetcher.ts +0 -200
- package/src/security/install-tracking.ts +0 -319
- package/src/security/license-pubkey.generated.ts +0 -30
- package/src/security/license-response-verifier.ts +0 -149
- package/src/security/local-fingerprint.ts +0 -225
- package/src/security/manifest-cache.ts +0 -333
- package/src/security/manifest-schema.ts +0 -129
- package/src/security/registry-pubkey.generated.ts +0 -35
- package/src/security/telemetry.ts +0 -320
- package/src/security-scorer.ts +0 -405
- package/src/security-utils.ts +0 -133
- package/src/sentinel-db.ts +0 -580
- package/src/sentinel-scanner.ts +0 -406
- package/src/sentinel-tools.ts +0 -513
- package/src/sentinel-types.ts +0 -140
- package/src/server-dispatch.ts +0 -225
- package/src/server.ts +0 -107
- package/src/session-archiver.ts +0 -111
- package/src/session-state-generator.ts +0 -174
- package/src/team-knowledge.ts +0 -407
- package/src/tool-db-needs.ts +0 -232
- package/src/tools.ts +0 -1206
- package/src/transcript-parser.ts +0 -458
- package/src/trpc-index.ts +0 -215
- package/src/validate-features-runner.ts +0 -107
- package/src/validation-engine.ts +0 -358
- package/src/watch/daemon.ts +0 -385
- package/src/watch/lockfile-detector.ts +0 -65
- package/src/watch/paths.ts +0 -279
- package/src/watch/state.ts +0 -178
package/src/import-resolver.ts
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Massu. All rights reserved.
|
|
2
|
-
// Licensed under BSL 1.1 - see LICENSE file for details.
|
|
3
|
-
|
|
4
|
-
import { readFileSync, existsSync, statSync } from 'fs';
|
|
5
|
-
import { resolve, dirname, join } from 'path';
|
|
6
|
-
import type Database from 'better-sqlite3';
|
|
7
|
-
import { getResolvedPaths, getProjectRoot } from './config.ts';
|
|
8
|
-
import { ensureWithinRoot } from './security-utils.ts';
|
|
9
|
-
import { t } from './lib/sql-table-names.ts';
|
|
10
|
-
|
|
11
|
-
interface ImportEdge {
|
|
12
|
-
source_file: string;
|
|
13
|
-
target_file: string;
|
|
14
|
-
import_type: 'named' | 'default' | 'namespace' | 'side_effect' | 'dynamic';
|
|
15
|
-
imported_names: string; // JSON array
|
|
16
|
-
line: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface ParsedImport {
|
|
20
|
-
type: 'named' | 'default' | 'namespace' | 'side_effect' | 'dynamic';
|
|
21
|
-
names: string[];
|
|
22
|
-
specifier: string;
|
|
23
|
-
line: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Parse import statements from TypeScript/JavaScript source code.
|
|
28
|
-
*/
|
|
29
|
-
export function parseImports(source: string): ParsedImport[] {
|
|
30
|
-
const imports: ParsedImport[] = [];
|
|
31
|
-
const lines = source.split('\n');
|
|
32
|
-
|
|
33
|
-
for (let i = 0; i < lines.length; i++) {
|
|
34
|
-
const line = lines[i];
|
|
35
|
-
const lineNum = i + 1;
|
|
36
|
-
|
|
37
|
-
// Skip comments
|
|
38
|
-
if (line.trimStart().startsWith('//') || line.trimStart().startsWith('*')) continue;
|
|
39
|
-
|
|
40
|
-
// Named imports: import { Foo, Bar } from 'module'
|
|
41
|
-
const namedMatch = line.match(/import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/);
|
|
42
|
-
if (namedMatch) {
|
|
43
|
-
const names = namedMatch[1].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim()).filter(Boolean);
|
|
44
|
-
imports.push({ type: 'named', names, specifier: namedMatch[2], line: lineNum });
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Default import: import Foo from 'module'
|
|
49
|
-
const defaultMatch = line.match(/import\s+([A-Z_$][\w$]*)\s+from\s+['"]([^'"]+)['"]/);
|
|
50
|
-
if (defaultMatch) {
|
|
51
|
-
imports.push({ type: 'default', names: [defaultMatch[1]], specifier: defaultMatch[2], line: lineNum });
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Default + named: import Foo, { Bar } from 'module'
|
|
56
|
-
const mixedMatch = line.match(/import\s+([A-Z_$][\w$]*)\s*,\s*\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/);
|
|
57
|
-
if (mixedMatch) {
|
|
58
|
-
const names = [mixedMatch[1], ...mixedMatch[2].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim()).filter(Boolean)];
|
|
59
|
-
imports.push({ type: 'named', names, specifier: mixedMatch[3], line: lineNum });
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Namespace import: import * as Foo from 'module'
|
|
64
|
-
const namespaceMatch = line.match(/import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]/);
|
|
65
|
-
if (namespaceMatch) {
|
|
66
|
-
imports.push({ type: 'namespace', names: [namespaceMatch[1]], specifier: namespaceMatch[2], line: lineNum });
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Type imports: import type { Foo } from 'module'
|
|
71
|
-
const typeMatch = line.match(/import\s+type\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/);
|
|
72
|
-
if (typeMatch) {
|
|
73
|
-
const names = typeMatch[1].split(',').map(n => n.trim().split(/\s+as\s+/)[0].trim()).filter(Boolean);
|
|
74
|
-
imports.push({ type: 'named', names, specifier: typeMatch[2], line: lineNum });
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Side effect import: import 'module'
|
|
79
|
-
const sideEffectMatch = line.match(/^import\s+['"]([^'"]+)['"]/);
|
|
80
|
-
if (sideEffectMatch) {
|
|
81
|
-
imports.push({ type: 'side_effect', names: [], specifier: sideEffectMatch[1], line: lineNum });
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Dynamic import: await import('module') or import('module')
|
|
86
|
-
const dynamicMatch = line.match(/(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
87
|
-
if (dynamicMatch) {
|
|
88
|
-
imports.push({ type: 'dynamic', names: [], specifier: dynamicMatch[1], line: lineNum });
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return imports;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Resolve an import specifier to an absolute file path.
|
|
98
|
-
* Returns null for external packages (bare imports).
|
|
99
|
-
*/
|
|
100
|
-
export function resolveImportPath(specifier: string, fromFile: string): string | null {
|
|
101
|
-
// Skip external/bare imports (no . or @ prefix)
|
|
102
|
-
if (!specifier.startsWith('.') && !specifier.startsWith('@/')) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
let basePath: string;
|
|
107
|
-
|
|
108
|
-
// Handle @/ alias -> src/
|
|
109
|
-
if (specifier.startsWith('@/')) {
|
|
110
|
-
const paths = getResolvedPaths();
|
|
111
|
-
basePath = resolve(paths.pathAlias['@'] ?? paths.srcDir, specifier.slice(2));
|
|
112
|
-
} else {
|
|
113
|
-
// Relative path
|
|
114
|
-
basePath = resolve(dirname(fromFile), specifier);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Try exact path first
|
|
118
|
-
if (existsSync(basePath) && !isDirectory(basePath)) {
|
|
119
|
-
return toRelative(basePath);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Try with extensions
|
|
123
|
-
const resolvedPaths = getResolvedPaths();
|
|
124
|
-
for (const ext of resolvedPaths.extensions) {
|
|
125
|
-
const withExt = basePath + ext;
|
|
126
|
-
if (existsSync(withExt)) {
|
|
127
|
-
return toRelative(withExt);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Try index files (if path is a directory or could be)
|
|
132
|
-
for (const indexFile of resolvedPaths.indexFiles) {
|
|
133
|
-
const indexPath = join(basePath, indexFile);
|
|
134
|
-
if (existsSync(indexPath)) {
|
|
135
|
-
return toRelative(indexPath);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function isDirectory(path: string): boolean {
|
|
143
|
-
try {
|
|
144
|
-
return statSync(path).isDirectory();
|
|
145
|
-
} catch {
|
|
146
|
-
// Path doesn't exist or is inaccessible
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function toRelative(absPath: string): string {
|
|
152
|
-
const root = getProjectRoot();
|
|
153
|
-
if (absPath.startsWith(root)) {
|
|
154
|
-
return absPath.slice(root.length + 1);
|
|
155
|
-
}
|
|
156
|
-
return absPath;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Build the full import graph for all files in CodeGraph.
|
|
161
|
-
* Stores results in massu_imports table.
|
|
162
|
-
*/
|
|
163
|
-
export function buildImportIndex(dataDb: Database.Database, codegraphDb: Database.Database): number {
|
|
164
|
-
// Get all files from CodeGraph
|
|
165
|
-
const files = codegraphDb.prepare("SELECT path FROM files WHERE path LIKE 'src/%'").all() as { path: string }[];
|
|
166
|
-
|
|
167
|
-
// Clear existing import edges
|
|
168
|
-
dataDb.exec(`DELETE FROM ${t('imports')}`);
|
|
169
|
-
|
|
170
|
-
const insertStmt = dataDb.prepare(
|
|
171
|
-
`INSERT INTO ${t('imports')} (source_file, target_file, import_type, imported_names, line) VALUES (?, ?, ?, ?, ?)`
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
let edgeCount = 0;
|
|
175
|
-
const projectRoot = getProjectRoot();
|
|
176
|
-
|
|
177
|
-
const insertMany = dataDb.transaction((edges: ImportEdge[]) => {
|
|
178
|
-
for (const edge of edges) {
|
|
179
|
-
insertStmt.run(edge.source_file, edge.target_file, edge.import_type, edge.imported_names, edge.line);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
const batchSize = 500;
|
|
184
|
-
let batch: ImportEdge[] = [];
|
|
185
|
-
|
|
186
|
-
for (const file of files) {
|
|
187
|
-
const absPath = ensureWithinRoot(resolve(projectRoot, file.path), projectRoot);
|
|
188
|
-
if (!existsSync(absPath)) continue;
|
|
189
|
-
|
|
190
|
-
let source: string;
|
|
191
|
-
try {
|
|
192
|
-
source = readFileSync(absPath, 'utf-8');
|
|
193
|
-
} catch {
|
|
194
|
-
// Skip unreadable source files
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const imports = parseImports(source);
|
|
199
|
-
|
|
200
|
-
for (const imp of imports) {
|
|
201
|
-
const targetPath = resolveImportPath(imp.specifier, absPath);
|
|
202
|
-
if (!targetPath) continue; // Skip external packages
|
|
203
|
-
|
|
204
|
-
batch.push({
|
|
205
|
-
source_file: file.path,
|
|
206
|
-
target_file: targetPath,
|
|
207
|
-
import_type: imp.type,
|
|
208
|
-
imported_names: JSON.stringify(imp.names),
|
|
209
|
-
line: imp.line,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
edgeCount++;
|
|
213
|
-
|
|
214
|
-
if (batch.length >= batchSize) {
|
|
215
|
-
insertMany(batch);
|
|
216
|
-
batch = [];
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (batch.length > 0) {
|
|
222
|
-
insertMany(batch);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return edgeCount;
|
|
226
|
-
}
|
package/src/knowledge-db.ts
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Massu. All rights reserved.
|
|
2
|
-
// Licensed under BSL 1.1 - see LICENSE file for details.
|
|
3
|
-
|
|
4
|
-
import Database from 'better-sqlite3';
|
|
5
|
-
import { dirname } from 'path';
|
|
6
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
7
|
-
import { getConfig, getResolvedPaths } from './config.ts';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Connection to Massu Knowledge's SQLite database.
|
|
11
|
-
* Stores indexed .claude/ knowledge: rules, patterns, incidents, verifications, cross-references.
|
|
12
|
-
* Separate from codegraph.db (CodeGraph data) and memory.db (session memory).
|
|
13
|
-
*/
|
|
14
|
-
export function getKnowledgeDb(): Database.Database {
|
|
15
|
-
const dbPath = getResolvedPaths().knowledgeDbPath;
|
|
16
|
-
const dir = dirname(dbPath);
|
|
17
|
-
if (!existsSync(dir)) {
|
|
18
|
-
mkdirSync(dir, { recursive: true });
|
|
19
|
-
}
|
|
20
|
-
const db = new Database(dbPath);
|
|
21
|
-
db.pragma('journal_mode = WAL');
|
|
22
|
-
db.pragma('foreign_keys = ON');
|
|
23
|
-
initKnowledgeSchema(db);
|
|
24
|
-
return db;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function initKnowledgeSchema(db: Database.Database): void {
|
|
28
|
-
db.exec(`
|
|
29
|
-
-- Core document chunks (parsed from .claude/**/*.md)
|
|
30
|
-
CREATE TABLE IF NOT EXISTS knowledge_documents (
|
|
31
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
32
|
-
file_path TEXT NOT NULL,
|
|
33
|
-
category TEXT NOT NULL,
|
|
34
|
-
title TEXT NOT NULL,
|
|
35
|
-
description TEXT,
|
|
36
|
-
content_hash TEXT NOT NULL,
|
|
37
|
-
indexed_at TEXT NOT NULL,
|
|
38
|
-
indexed_at_epoch INTEGER NOT NULL
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_kd_filepath ON knowledge_documents(file_path);
|
|
42
|
-
CREATE INDEX IF NOT EXISTS idx_kd_category ON knowledge_documents(category);
|
|
43
|
-
|
|
44
|
-
-- Structured chunks within documents
|
|
45
|
-
CREATE TABLE IF NOT EXISTS knowledge_chunks (
|
|
46
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47
|
-
document_id INTEGER NOT NULL REFERENCES knowledge_documents(id) ON DELETE CASCADE,
|
|
48
|
-
chunk_type TEXT NOT NULL CHECK(chunk_type IN (
|
|
49
|
-
'section', 'table_row', 'code_block', 'rule', 'incident', 'pattern', 'command', 'mismatch'
|
|
50
|
-
)),
|
|
51
|
-
heading TEXT,
|
|
52
|
-
content TEXT NOT NULL,
|
|
53
|
-
line_start INTEGER,
|
|
54
|
-
line_end INTEGER,
|
|
55
|
-
metadata TEXT DEFAULT '{}'
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
CREATE INDEX IF NOT EXISTS idx_kc_doc ON knowledge_chunks(document_id);
|
|
59
|
-
CREATE INDEX IF NOT EXISTS idx_kc_type ON knowledge_chunks(chunk_type);
|
|
60
|
-
CREATE INDEX IF NOT EXISTS idx_kc_heading ON knowledge_chunks(heading);
|
|
61
|
-
|
|
62
|
-
-- Canonical Rules index
|
|
63
|
-
CREATE TABLE IF NOT EXISTS knowledge_rules (
|
|
64
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
65
|
-
rule_id TEXT UNIQUE NOT NULL,
|
|
66
|
-
rule_text TEXT NOT NULL,
|
|
67
|
-
vr_type TEXT,
|
|
68
|
-
reference_path TEXT,
|
|
69
|
-
severity TEXT DEFAULT 'HIGH',
|
|
70
|
-
prevention_summary TEXT
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
CREATE INDEX IF NOT EXISTS idx_kr_id ON knowledge_rules(rule_id);
|
|
74
|
-
|
|
75
|
-
-- Verification Requirements index
|
|
76
|
-
CREATE TABLE IF NOT EXISTS knowledge_verifications (
|
|
77
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
78
|
-
vr_type TEXT UNIQUE NOT NULL,
|
|
79
|
-
command TEXT NOT NULL,
|
|
80
|
-
expected TEXT NOT NULL,
|
|
81
|
-
use_when TEXT NOT NULL,
|
|
82
|
-
catches TEXT,
|
|
83
|
-
category TEXT
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
CREATE INDEX IF NOT EXISTS idx_kv_type ON knowledge_verifications(vr_type);
|
|
87
|
-
CREATE INDEX IF NOT EXISTS idx_kv_category ON knowledge_verifications(category);
|
|
88
|
-
|
|
89
|
-
-- Incident index
|
|
90
|
-
CREATE TABLE IF NOT EXISTS knowledge_incidents (
|
|
91
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
92
|
-
incident_num INTEGER UNIQUE NOT NULL,
|
|
93
|
-
date TEXT NOT NULL,
|
|
94
|
-
type TEXT NOT NULL,
|
|
95
|
-
gap_found TEXT NOT NULL,
|
|
96
|
-
prevention TEXT NOT NULL,
|
|
97
|
-
cr_added TEXT,
|
|
98
|
-
root_cause TEXT,
|
|
99
|
-
user_quote TEXT
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
CREATE INDEX IF NOT EXISTS idx_ki_num ON knowledge_incidents(incident_num);
|
|
103
|
-
CREATE INDEX IF NOT EXISTS idx_ki_type ON knowledge_incidents(type);
|
|
104
|
-
CREATE INDEX IF NOT EXISTS idx_ki_cr ON knowledge_incidents(cr_added);
|
|
105
|
-
|
|
106
|
-
-- Schema mismatch quick lookup
|
|
107
|
-
-- P-H013 (plan-stage-c-high-batch): the source column no longer has a
|
|
108
|
-
-- SQL DEFAULT. Previously the value was a JS template-literal
|
|
109
|
-
-- interpolation baked into the customer SQLite at schema creation
|
|
110
|
-
-- time, so later config changes were ignored. Default is now applied
|
|
111
|
-
-- at INSERT time via getConfig().conventions.knowledgeSourceFiles[0]
|
|
112
|
-
-- in knowledge-indexer.ts -- a runtime config lookup that reflects
|
|
113
|
-
-- the customers current config.
|
|
114
|
-
CREATE TABLE IF NOT EXISTS knowledge_schema_mismatches (
|
|
115
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
116
|
-
table_name TEXT NOT NULL,
|
|
117
|
-
wrong_column TEXT NOT NULL,
|
|
118
|
-
correct_column TEXT NOT NULL,
|
|
119
|
-
source TEXT NOT NULL
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
CREATE INDEX IF NOT EXISTS idx_ksm_table ON knowledge_schema_mismatches(table_name);
|
|
123
|
-
|
|
124
|
-
-- Cross-reference graph
|
|
125
|
-
CREATE TABLE IF NOT EXISTS knowledge_edges (
|
|
126
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
127
|
-
source_type TEXT NOT NULL,
|
|
128
|
-
source_id TEXT NOT NULL,
|
|
129
|
-
target_type TEXT NOT NULL,
|
|
130
|
-
target_id TEXT NOT NULL,
|
|
131
|
-
edge_type TEXT NOT NULL
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
CREATE INDEX IF NOT EXISTS idx_ke_source ON knowledge_edges(source_type, source_id);
|
|
135
|
-
CREATE INDEX IF NOT EXISTS idx_ke_target ON knowledge_edges(target_type, target_id);
|
|
136
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_ke_unique ON knowledge_edges(source_type, source_id, target_type, target_id, edge_type);
|
|
137
|
-
|
|
138
|
-
-- Staleness tracking
|
|
139
|
-
CREATE TABLE IF NOT EXISTS knowledge_meta (
|
|
140
|
-
key TEXT PRIMARY KEY,
|
|
141
|
-
value TEXT NOT NULL
|
|
142
|
-
);
|
|
143
|
-
`);
|
|
144
|
-
|
|
145
|
-
// FTS5 in separate exec (can fail if schema mismatch on existing table)
|
|
146
|
-
try {
|
|
147
|
-
db.exec(`
|
|
148
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_fts USING fts5(
|
|
149
|
-
heading, content, chunk_type, file_path
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
CREATE TRIGGER IF NOT EXISTS kc_fts_insert AFTER INSERT ON knowledge_chunks BEGIN
|
|
153
|
-
INSERT INTO knowledge_fts(rowid, heading, content, chunk_type, file_path)
|
|
154
|
-
SELECT new.id, new.heading, new.content, new.chunk_type, kd.file_path
|
|
155
|
-
FROM knowledge_documents kd WHERE kd.id = new.document_id;
|
|
156
|
-
END;
|
|
157
|
-
|
|
158
|
-
CREATE TRIGGER IF NOT EXISTS kc_fts_delete AFTER DELETE ON knowledge_chunks BEGIN
|
|
159
|
-
INSERT INTO knowledge_fts(knowledge_fts, rowid, heading, content, chunk_type, file_path)
|
|
160
|
-
SELECT 'delete', old.id, old.heading, old.content, old.chunk_type, kd.file_path
|
|
161
|
-
FROM knowledge_documents kd WHERE kd.id = old.document_id;
|
|
162
|
-
END;
|
|
163
|
-
|
|
164
|
-
CREATE TRIGGER IF NOT EXISTS kc_fts_update AFTER UPDATE ON knowledge_chunks BEGIN
|
|
165
|
-
INSERT INTO knowledge_fts(knowledge_fts, rowid, heading, content, chunk_type, file_path)
|
|
166
|
-
SELECT 'delete', old.id, old.heading, old.content, old.chunk_type, kd.file_path
|
|
167
|
-
FROM knowledge_documents kd WHERE kd.id = old.document_id;
|
|
168
|
-
INSERT INTO knowledge_fts(rowid, heading, content, chunk_type, file_path)
|
|
169
|
-
SELECT new.id, new.heading, new.content, new.chunk_type, kd.file_path
|
|
170
|
-
FROM knowledge_documents kd WHERE kd.id = new.document_id;
|
|
171
|
-
END;
|
|
172
|
-
`);
|
|
173
|
-
} catch {
|
|
174
|
-
// FTS5 table may already exist with different schema — not fatal
|
|
175
|
-
}
|
|
176
|
-
}
|