diff --git a/gitnexus/src/core/lbug/lbug-adapter.ts b/gitnexus/src/core/lbug/lbug-adapter.ts index bd40617976..ff8345d069 100644 --- a/gitnexus/src/core/lbug/lbug-adapter.ts +++ b/gitnexus/src/core/lbug/lbug-adapter.ts @@ -336,6 +336,9 @@ const getCopyQuery = (table: NodeTableName, filePath: string): string => { if (table === 'Process') { return `COPY ${t}(id, label, heuristicLabel, processType, stepCount, communities, entryPointId, terminalId) FROM "${filePath}" ${COPY_CSV_OPTS}`; } + if (table === 'Section') { + return `COPY ${t}(id, name, filePath, startLine, endLine, level, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`; + } if (table === 'Method') { return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description, parameterCount, returnType) FROM "${filePath}" ${COPY_CSV_OPTS}`; } @@ -380,6 +383,9 @@ export const insertNodeToLbug = async ( query = `CREATE (n:File {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, content: ${escapeValue(properties.content || '')}})`; } else if (label === 'Folder') { query = `CREATE (n:Folder {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}})`; + } else if (label === 'Section') { + const descPart = properties.description ? `, description: ${escapeValue(properties.description)}` : ''; + query = `CREATE (n:Section {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, level: ${properties.level || 1}, content: ${escapeValue(properties.content || '')}${descPart}})`; } else if (TABLES_WITH_EXPORTED.has(label)) { const descPart = properties.description ? `, description: ${escapeValue(properties.description)}` : ''; query = `CREATE (n:${t} {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, isExported: ${!!properties.isExported}, content: ${escapeValue(properties.content || '')}${descPart}})`; @@ -451,6 +457,9 @@ export const batchInsertNodesToLbug = async ( query = `MERGE (n:File {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.content = ${escapeValue(properties.content || '')}`; } else if (label === 'Folder') { query = `MERGE (n:Folder {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}`; + } else if (label === 'Section') { + const descPart = properties.description ? `, n.description = ${escapeValue(properties.description)}` : ''; + query = `MERGE (n:Section {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.level = ${properties.level || 1}, n.content = ${escapeValue(properties.content || '')}${descPart}`; } else if (TABLES_WITH_EXPORTED.has(label)) { const descPart = properties.description ? `, n.description = ${escapeValue(properties.description)}` : ''; query = `MERGE (n:${t} {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.isExported = ${!!properties.isExported}, n.content = ${escapeValue(properties.content || '')}${descPart}`; diff --git a/gitnexus/src/core/lbug/schema.ts b/gitnexus/src/core/lbug/schema.ts index c082924669..a47aa9674a 100644 --- a/gitnexus/src/core/lbug/schema.ts +++ b/gitnexus/src/core/lbug/schema.ts @@ -13,7 +13,7 @@ // NODE TABLE NAMES // ============================================================================ export const NODE_TABLES = [ - 'File', 'Folder', 'Function', 'Class', 'Interface', 'Method', 'CodeElement', 'Community', 'Process', + 'File', 'Folder', 'Function', 'Class', 'Interface', 'Method', 'CodeElement', 'Community', 'Process', 'Section', // Multi-language support 'Struct', 'Enum', 'Macro', 'Typedef', 'Union', 'Namespace', 'Trait', 'Impl', 'TypeAlias', 'Const', 'Static', 'Property', 'Record', 'Delegate', 'Annotation', 'Constructor', 'Template', 'Module' @@ -238,6 +238,7 @@ CREATE REL TABLE ${REL_TABLE_NAME} ( FROM File TO \`Constructor\`, FROM File TO \`Template\`, FROM File TO \`Module\`, + FROM File TO Section, FROM Folder TO Folder, FROM Folder TO File, FROM Function TO Function, @@ -462,6 +463,8 @@ export const NODE_SCHEMA_QUERIES = [ CONSTRUCTOR_SCHEMA, TEMPLATE_SCHEMA, MODULE_SCHEMA, + // Markdown support + SECTION_SCHEMA, ]; export const REL_SCHEMA_QUERIES = [ diff --git a/gitnexus/test/integration/skills-e2e.test.ts b/gitnexus/test/integration/skills-e2e.test.ts index 31f836179a..58a98e984c 100644 --- a/gitnexus/test/integration/skills-e2e.test.ts +++ b/gitnexus/test/integration/skills-e2e.test.ts @@ -2389,8 +2389,16 @@ export function createEntry(level: string, msg: string) { /* CI timeout tolerance */ if (result1.status === null || result2.status === null) return; - expect(result1.status).toBe(0); - expect(result2.status).toBe(0); + expect(result1.status, [ + `first analyze --skills exited with code ${result1.status}`, + `stdout: ${result1.stdout?.slice(0, 500)}`, + `stderr: ${result1.stderr?.slice(0, 500)}`, + ].join('\n')).toBe(0); + expect(result2.status, [ + `second analyze --skills exited with code ${result2.status}`, + `stdout: ${result2.stdout?.slice(0, 500)}`, + `stderr: ${result2.stderr?.slice(0, 500)}`, + ].join('\n')).toBe(0); const generatedDir = path.join(tmpDir, '.claude', 'skills', 'generated'); expect(fs.existsSync(generatedDir)).toBe(true); diff --git a/gitnexus/test/unit/schema.test.ts b/gitnexus/test/unit/schema.test.ts index 87e369652f..75235f0e4d 100644 --- a/gitnexus/test/unit/schema.test.ts +++ b/gitnexus/test/unit/schema.test.ts @@ -40,7 +40,7 @@ describe('LadybugDB Schema', () => { it('has expected total count', () => { // 9 core + 18 multi-language = 27 - expect(NODE_TABLES).toHaveLength(27); + expect(NODE_TABLES).toHaveLength(28); }); }); @@ -164,7 +164,7 @@ describe('LadybugDB Schema', () => { describe('schema query ordering', () => { it('NODE_SCHEMA_QUERIES has correct count', () => { - expect(NODE_SCHEMA_QUERIES).toHaveLength(27); + expect(NODE_SCHEMA_QUERIES).toHaveLength(28); }); it('REL_SCHEMA_QUERIES has one relation table', () => { @@ -173,7 +173,7 @@ describe('LadybugDB Schema', () => { it('SCHEMA_QUERIES includes all node + rel + embedding schemas', () => { // 27 node + 1 rel + 1 embedding = 29 - expect(SCHEMA_QUERIES).toHaveLength(29); + expect(SCHEMA_QUERIES).toHaveLength(30); }); it('node schemas come before relation schemas in SCHEMA_QUERIES', () => {