Candidate manifest 8b4ab31014a124ec0e3abba44238976d6f4c9af48cbdb36c2c77d18f0137f888 from Darkwing's round 2 packet (0a4076e8e), on BASE1223a0f37. No manifest path changed between BASE and the landing target. Filbert approved round 2 in 28468, closing C1 and D1 from round 1 (28464). Sage reran the full gate at the landing target with the candidate applied. The replay acceptance follows ruling sage-0204. Co-Authored-By: Claude Opus 5.5 <[email protected]>
58 lines
2.6 KiB
JavaScript
58 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
// Test fixture for land-work (row 116, #1610): writes rows into a bus
|
|
// database through the real Store, so the schema and its digest are the
|
|
// Store's own and land-work's read check passes.
|
|
//
|
|
// node scripts/land-work/fixture.mjs <dataRoot> <rows.json>
|
|
//
|
|
// rows.json is an array of { "table": "decisions" | "decision_events" |
|
|
// "events", ...columns }. Rows go in in array order, in one transaction.
|
|
// Object values (body, options) are stored as JSON text. A missing `at` is
|
|
// now, a missing events or decisions `id` is a fresh UUID, and decisions
|
|
// default to the shape a PM's merge raise has. The data root is made if
|
|
// missing. Tests only: the Store's writer lock refuses a database that
|
|
// already has a writer.
|
|
import { readFileSync, mkdirSync } from 'node:fs';
|
|
import { randomUUID } from 'node:crypto';
|
|
import { pathToFileURL } from 'node:url';
|
|
import { Store } from '../../packages/bus/src/store.mjs';
|
|
|
|
const TABLES = {
|
|
decisions: ['seq', 'id', 'at', 'business', 'project', 'raised_by_role', 'raised_by_run', 'class', 'action',
|
|
'route_to', 'question', 'options', 'recommendation', 'task_ref', 'requirement_ref', 'blocking', 'supersedes'],
|
|
decision_events: ['seq', 'decision', 'at', 'op', 'by', 'choice', 'note', 'via'],
|
|
events: ['seq', 'id', 'at', 'business', 'kind', 'actor_role', 'actor_run', 'subject', 'corrects', 'body'],
|
|
};
|
|
const DEFAULTS = {
|
|
decisions: { raised_by_role: 'pm', raised_by_run: 'rfixture', class: 'gated', route_to: 'human',
|
|
recommendation: 'yes', blocking: 0 },
|
|
decision_events: {},
|
|
events: {},
|
|
};
|
|
|
|
export function writeRows(dataRoot, rows) {
|
|
mkdirSync(dataRoot, { recursive: true, mode: 0o700 });
|
|
const store = new Store(dataRoot);
|
|
try {
|
|
store.transaction(() => {
|
|
for (const row of rows) {
|
|
const columns = TABLES[row.table];
|
|
if (!columns) throw Error(`unknown table ${row.table}`);
|
|
const r = { ...DEFAULTS[row.table], ...row };
|
|
r.at ??= new Date().toISOString();
|
|
if (row.table !== 'decision_events') r.id ??= randomUUID();
|
|
const used = columns.filter((c) => r[c] !== undefined);
|
|
const values = used.map((c) => (r[c] !== null && typeof r[c] === 'object' ? JSON.stringify(r[c]) : r[c]));
|
|
store.run(`INSERT INTO ${row.table} (${used.join(',')}) VALUES (${used.map(() => '?').join(',')})`, ...values);
|
|
}
|
|
});
|
|
} finally {
|
|
store.close();
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
const [dataRoot, file] = process.argv.slice(2);
|
|
writeRows(dataRoot, JSON.parse(readFileSync(file, 'utf8')));
|
|
}
|