fix: close all audit blockers — RuntimeApp fully wired, recovery restored
RuntimeApp.start(): - Initialize DB + run migrations on startup - Register built-in tools via ToolRegistry (INV-3) - Wire EventStore with DatabaseManager transaction manager - Wire Scheduler.set_task_repo() + rebuild_from_db() (INV-5) - Real worker cancellation + DB close in shutdown() - Session DB path fixed: .air/local/sessions/<id>/session.db DeveloperLogEncryptor: - Restore throws-on-no-key (security invariant, test passes) C++ toolchain: - CppProjectDetector.command_exists(): check PATH via which - CppProjectDetector.find_cpp_sources(): real recursive fs walk - CppTestRunner.parse_ctest_output: fix regex for real ctest format Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
* @module packages/toolchain-cpp/src/detect/CppProjectDetector
|
||||
*/
|
||||
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { existsSync, readFileSync, readdirSync, statSync } from 'fs'
|
||||
import { join, extname } from 'path'
|
||||
|
||||
export interface CppDetectOutput {
|
||||
project_type: 'cmake' | 'make' | 'unknown'
|
||||
@@ -63,12 +63,41 @@ export class CppProjectDetector {
|
||||
}
|
||||
|
||||
private command_exists(cmd: string): boolean {
|
||||
// Simplified check
|
||||
return existsSync(`/usr/bin/${cmd}`) || existsSync(`/usr/local/bin/${cmd}`)
|
||||
const paths = [
|
||||
`/usr/bin/${cmd}`,
|
||||
`/usr/local/bin/${cmd}`,
|
||||
`/usr/lib/${cmd}`,
|
||||
process.env.HOME ? `${process.env.HOME}/.local/bin/${cmd}` : null,
|
||||
].filter(Boolean) as string[]
|
||||
if (paths.some(p => existsSync(p))) return true
|
||||
// Check PATH
|
||||
try {
|
||||
const { execFileSync } = require('child_process')
|
||||
execFileSync('which', [cmd], { stdio: 'pipe', timeout: 3000 })
|
||||
return true
|
||||
} catch { return false }
|
||||
}
|
||||
|
||||
private find_cpp_sources(): string[] {
|
||||
// Would recursively find .cpp/.cc/.cxx/.h/.hpp files
|
||||
return []
|
||||
const root = this.project_root
|
||||
const results: string[] = []
|
||||
const extensions = new Set(['.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.hxx'])
|
||||
const walk = (dir: string, depth = 0) => {
|
||||
if (depth > 6) return
|
||||
try {
|
||||
const entries = readdirSync(dir)
|
||||
for (const e of entries) {
|
||||
if (e.startsWith('.') || e === 'node_modules' || e === 'build') continue
|
||||
const full = join(dir, e)
|
||||
try {
|
||||
const s = statSync(full)
|
||||
if (s.isDirectory()) walk(full, depth + 1)
|
||||
else if (extensions.has(extname(e))) results.push(full)
|
||||
} catch { /* skip */ }
|
||||
}
|
||||
} catch { /* skip */ }
|
||||
}
|
||||
walk(root)
|
||||
return results
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,30 @@ export class CppTestRunner {
|
||||
}
|
||||
|
||||
private parse_ctest_output(output: string): { total: number; passed: number; failed: number } {
|
||||
const match = output.match(/(\d+)\/?(?:\d+)?\s*Test.*#\d+:|Tests\s+passed.*(\d+)\s+total/i)
|
||||
if (match) {
|
||||
return { total: parseInt(match[1]) || 0, passed: parseInt(match[1]) || 0, failed: 0 }
|
||||
// ctest format: "X% tests passed, Y tests failed out of Z"
|
||||
const summary = output.match(/(\d+)%\s+tests\s+passed,\s+(\d+)\s+tests?\s+failed\s+out\s+of\s+(\d+)/i)
|
||||
if (summary) {
|
||||
const total = parseInt(summary[3])
|
||||
const failed = parseInt(summary[2])
|
||||
return { total, failed, passed: total - failed }
|
||||
}
|
||||
// Alternate: "Tests passed: N, Tests failed: M"
|
||||
const alt = output.match(/Tests\s+passed:\s*(\d+),\s+Tests\s+failed:\s*(\d+)/i)
|
||||
if (alt) {
|
||||
const passed = parseInt(alt[1])
|
||||
const failed = parseInt(alt[2])
|
||||
return { total: passed + failed, passed, failed }
|
||||
}
|
||||
// ctest line: "X/Y Test #..."
|
||||
const lines = output.split('\n').filter(l => /\d+\/\d+\s+Test/.test(l))
|
||||
if (lines.length > 0) {
|
||||
const last = lines[lines.length - 1]
|
||||
const m = last.match(/(\d+)\/(\d+)/)
|
||||
if (m) {
|
||||
const total = parseInt(m[2])
|
||||
const passed = parseInt(m[1])
|
||||
return { total, passed, failed: total - passed }
|
||||
}
|
||||
}
|
||||
return { total: 0, passed: 0, failed: 0 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user