mirror of
https://github.com/joelhooks/joelclaw.git
synced 2026-09-19 01:24:04 +08:00
900c10325f
joelclaw recall and knowledge search open ~/.joelclaw/search/critical.db first (29,906 docs: observations, Brain pages, vault, knowledge, archived memory) with per-source freshness and clean fallback to Typesense on any SQLite failure — proven through the compiled binary. Builder holds an exclusive lock, refuses degraded or collapsed sources (caught five malformed live pages), and swaps atomically. Observer refs are honest source-labels (resolvableInRunsDev: false). Refuted once by adversarial verification (fallback crash, unsafe builder, fake backlinks); reworked and re-verified CONFIRMED on every count. Receipts: critical-port-verification.svx
58 lines
2.0 KiB
TypeScript
Executable File
58 lines
2.0 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
|
|
import { existsSync } from "node:fs"
|
|
import { resolve } from "node:path"
|
|
import { buildCriticalDb, DEFAULT_CRITICAL_DB_PATH } from "../packages/cli/src/lib/critical-search"
|
|
import { resolveTypesenseApiKey } from "../packages/cli/src/typesense-auth"
|
|
|
|
function option(name: string): string | undefined {
|
|
const index = process.argv.indexOf(name)
|
|
return index >= 0 ? process.argv[index + 1] : undefined
|
|
}
|
|
|
|
function hasFlag(name: string): boolean {
|
|
return process.argv.includes(name)
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
if (hasFlag("--help")) {
|
|
console.log("Usage: bun scripts/build-critical-search-db.ts [--db <path>] [--memory-archive <jsonl>] [--skip-typesense] [--allow-degraded-sources]")
|
|
console.log("Builds an atomic SQLite FTS5 critical projection. Only flagg may write the production database.")
|
|
return
|
|
}
|
|
|
|
const dbPath = resolve(option("--db")?.trim() || process.env.JOELCLAW_CRITICAL_DB || DEFAULT_CRITICAL_DB_PATH)
|
|
const archive = option("--memory-archive")?.trim()
|
|
if (archive && !existsSync(archive)) throw new Error(`Memory archive not found: ${archive}`)
|
|
|
|
let apiKey: string | undefined
|
|
let keyStatus = "skipped"
|
|
if (!hasFlag("--skip-typesense")) {
|
|
try {
|
|
apiKey = resolveTypesenseApiKey()
|
|
keyStatus = "leased"
|
|
} catch (error) {
|
|
keyStatus = `unavailable: ${error instanceof Error ? error.message : String(error)}`
|
|
}
|
|
}
|
|
|
|
const result = await buildCriticalDb({
|
|
dbPath,
|
|
typesenseApiKey: apiKey,
|
|
memoryArchivePath: archive,
|
|
allowDegradedSources: hasFlag("--allow-degraded-sources"),
|
|
})
|
|
|
|
console.log(JSON.stringify({
|
|
ok: true,
|
|
...result,
|
|
typesenseCredential: keyStatus,
|
|
note: "The builder uses read-only Typesense exports, an exclusive lock, required-source gates, and atomic replacement after SQLite integrity_check passes.",
|
|
}, null, 2))
|
|
}
|
|
|
|
await main().catch((error) => {
|
|
console.error(error instanceof Error ? error.message : String(error))
|
|
process.exit(1)
|
|
})
|