Main no longer opens desktop business SQLite. A single utility-process
storage owner holds the Assistant, Knowledge, attachment, document-result,
remote-binding and native model-ledger databases and runs whole domain
transactions; Main and Runtime callers use explicit async domain operations.
- Remove the Main readWithFallback path and the supervision worker's
separate business write connection; manifests are scanned read-only and
committed by the sole writer.
- Remote events are ACKed only after commit; process loss reports
unconfirmed writes instead of replaying them.
- Use native utilityProcess messaging with one in-flight bound (32) and
ordered waiting instead of capacity rejection and retries.
- Start the storage process before the window so startup overlaps.
- Keep short tool output in memory and store full output once in owned
storage; paging, branching, restart and deletion reuse that copy.
- Put required runtime launch files under goodbuddy-prefixed owned temp
directories and reclaim confirmed stale ones; stop writing duplicate
parsed.md.
- Add lint guards for SQLite ownership and architecture, concurrency
acceptance fixtures, and maintenance/architecture documentation.
Validation: typecheck and lint pass. Alternating baseline (edf019aa) vs
candidate runs show no regression on single-session, C01, C02, C04 and a
5-minute C06; Main p99 drops from ~21 ms to ~16.7 ms under concurrency.
Fresh portable copy (1.75M events) upgrade content unchanged; real-model
output paging passes with 4 external requests. Full npm test runs had
1-9 different timing-sensitive failures per run that pass when rerun.
Not covered: C03 review publication, C07 source body, app-level C05.
55 lines
3.4 KiB
TypeScript
55 lines
3.4 KiB
TypeScript
// Offline production-factory replay. The source is read-only; only a new backup is initialized.
|
|
import assert from 'node:assert/strict'
|
|
import { DatabaseSync, backup } from 'node:sqlite'
|
|
import { cpSync, existsSync, writeFileSync } from 'node:fs'
|
|
import { dirname, join, resolve } from 'node:path'
|
|
import { AssistantDatabase } from '../src/main/assistant/assistant-database'
|
|
import { createProductionSupervisorService } from '../src/main/assistant/supervision-production'
|
|
import { SupervisionModelPool } from '../src/main/assistant/supervision-model-pool'
|
|
import type { AgentRuntime } from '../src/main/agent/runtime'
|
|
import { asyncSupervisionStorage } from '../tests/support/async-supervision-storage'
|
|
|
|
async function main() {
|
|
const [sourcePath, destinationPath, runId] = process.argv.slice(2)
|
|
assert(sourcePath && destinationPath && runId)
|
|
assert(resolve(sourcePath) !== resolve(destinationPath) && !existsSync(destinationPath))
|
|
const source = new DatabaseSync(sourcePath, { readOnly: true })
|
|
const before = source.prepare('SELECT * FROM supervision_runs WHERE id = ?').get(runId)
|
|
assert(before)
|
|
const cached = source.prepare('SELECT output_json FROM supervision_review_navigation WHERE run_id = ? LIMIT 1').get(runId)
|
|
assert(cached, 'Replay requires a saved navigation response')
|
|
const { summary, changeDigest, openItems } = JSON.parse(String(cached.output_json))
|
|
await backup(source, destinationPath)
|
|
const notes = join(dirname(sourcePath), 'notes')
|
|
const copiedNotes = join(dirname(destinationPath), 'notes')
|
|
if (existsSync(notes) && !existsSync(copiedNotes)) cpSync(notes, copiedNotes, { recursive: true })
|
|
const db = new AssistantDatabase(destinationPath)
|
|
const pool = new SupervisionModelPool()
|
|
let calls = 0
|
|
const run: AgentRuntime['run'] = async function* (input) {
|
|
assert(input.prompt.includes('These inputs are navigation summaries'), 'No successful leaf may be replayed')
|
|
calls++
|
|
yield { type: 'text', requestId: input.requestId, delta: JSON.stringify({ summary, changeDigest, openItems }) }
|
|
yield { type: 'done', requestId: input.requestId }
|
|
}
|
|
try {
|
|
db.initialize(dirname(destinationPath))
|
|
const store = db.supervisionReviewStore()
|
|
const leaves = store.batches(runId, 20)
|
|
assert.equal(leaves.length, 6)
|
|
assert.equal(store.progress(runId).remainingSources, 0)
|
|
const service = createProductionSupervisorService(asyncSupervisionStorage(db).supervision, async () => ({ supervisorModelConcurrency: 1 }),
|
|
async () => ({ runtimeId: 'offline-replay', capability: 'chat', run } as AgentRuntime), pool)
|
|
const result = await service.resume(runId)
|
|
assert.equal(result.status, 'completed')
|
|
assert.deepEqual(store.batches(runId, 20), leaves)
|
|
assert.equal(calls, 4)
|
|
assert.deepEqual(source.prepare('SELECT * FROM supervision_runs WHERE id = ?').get(runId), before)
|
|
const report = { runId, status: result.status, retainedLeaves: leaves.length, offlineResponses: calls, paidCalls: 0,
|
|
originalUnchanged: true, progress: store.progress(runId), limitation: 'Saved successful navigation text replayed with optional arrays omitted; failed raw response was not persisted.' }
|
|
writeFileSync(`${destinationPath}.report.json`, JSON.stringify(report, null, 2))
|
|
console.log(JSON.stringify(report))
|
|
} finally { db.close(); pool.dispose(); source.close() }
|
|
}
|
|
void main().catch(error => { console.error(error); process.exitCode = 1 })
|