mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-03 19:34:24 +00:00
Align scheduler tables with roster and add drift check
This commit is contained in:
1 parent
f27929746e
commit
5b0cf980e9
4 files changed
+142
-17
No files matched your search
@@ -0,0 +1,122 @@
|
||||
import { readdir, readFile } from 'node:fs/promises';
|
||||
|
||||
const CONFIG = {
|
||||
daily: {
|
||||
schedulerFile: 'src/prompts/daily-scheduler.md',
|
||||
promptDir: 'src/prompts/daily',
|
||||
},
|
||||
weekly: {
|
||||
schedulerFile: 'src/prompts/weekly-scheduler.md',
|
||||
promptDir: 'src/prompts/weekly',
|
||||
},
|
||||
};
|
||||
|
||||
function parseTableRows(markdown, schedulerFile) {
|
||||
const rows = [];
|
||||
for (const line of markdown.split('\n')) {
|
||||
const match = line.match(/^\|\s*(\d+)\s*\|\s*([^|]+?)\s*\|\s*`([^`]+)`\s*\|\s*$/);
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rows.push({
|
||||
index: Number(match[1]),
|
||||
agent: match[2].trim(),
|
||||
promptFile: match[3].trim(),
|
||||
});
|
||||
}
|
||||
|
||||
if (rows.length === 0) {
|
||||
throw new Error(`No scheduler table rows found in ${schedulerFile}`);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
function diffLists(expected, actual) {
|
||||
return {
|
||||
missing: expected.filter((item) => !actual.includes(item)),
|
||||
extra: actual.filter((item) => !expected.includes(item)),
|
||||
};
|
||||
}
|
||||
|
||||
function validateScheduler(cadence, roster, rows, promptFiles) {
|
||||
const errors = [];
|
||||
|
||||
if (rows.length !== roster.length) {
|
||||
errors.push(
|
||||
`[${cadence}] row count mismatch: roster has ${roster.length}, table has ${rows.length}`,
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < rows.length; i += 1) {
|
||||
const row = rows[i];
|
||||
const expectedIndex = i + 1;
|
||||
if (row.index !== expectedIndex) {
|
||||
errors.push(`[${cadence}] row ${i + 1} has index ${row.index}, expected ${expectedIndex}`);
|
||||
}
|
||||
|
||||
const expectedAgent = roster[i];
|
||||
if (expectedAgent && row.agent !== expectedAgent) {
|
||||
errors.push(
|
||||
`[${cadence}] row ${i + 1} agent mismatch: table has "${row.agent}", roster expects "${expectedAgent}"`,
|
||||
);
|
||||
}
|
||||
|
||||
const expectedPromptFile = `${row.agent}.md`;
|
||||
if (row.promptFile !== expectedPromptFile) {
|
||||
errors.push(
|
||||
`[${cadence}] row ${i + 1} prompt file mismatch: table has "${row.promptFile}", expected "${expectedPromptFile}"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const tableAgents = rows.map((row) => row.agent);
|
||||
const rosterVsTable = diffLists(roster, tableAgents);
|
||||
if (rosterVsTable.missing.length > 0 || rosterVsTable.extra.length > 0) {
|
||||
errors.push(
|
||||
`[${cadence}] roster/table mismatch: missing in table [${rosterVsTable.missing.join(', ')}], extra in table [${rosterVsTable.extra.join(', ')}]`,
|
||||
);
|
||||
}
|
||||
|
||||
const rosterPromptFiles = roster.map((agent) => `${agent}.md`);
|
||||
const filesVsRoster = diffLists(rosterPromptFiles, promptFiles);
|
||||
if (filesVsRoster.missing.length > 0 || filesVsRoster.extra.length > 0) {
|
||||
errors.push(
|
||||
`[${cadence}] roster/files mismatch: missing files [${filesVsRoster.missing.join(', ')}], extra files [${filesVsRoster.extra.join(', ')}]`,
|
||||
);
|
||||
}
|
||||
|
||||
const filesVsTable = diffLists(promptFiles, rows.map((row) => row.promptFile));
|
||||
if (filesVsTable.missing.length > 0 || filesVsTable.extra.length > 0) {
|
||||
errors.push(
|
||||
`[${cadence}] table/files mismatch: missing in table [${filesVsTable.missing.join(', ')}], extra in table [${filesVsTable.extra.join(', ')}]`,
|
||||
);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const roster = JSON.parse(await readFile('src/prompts/roster.json', 'utf8'));
|
||||
|
||||
const allErrors = [];
|
||||
|
||||
for (const [cadence, cfg] of Object.entries(CONFIG)) {
|
||||
const schedulerMd = await readFile(cfg.schedulerFile, 'utf8');
|
||||
const rows = parseTableRows(schedulerMd, cfg.schedulerFile);
|
||||
const promptFiles = (await readdir(cfg.promptDir))
|
||||
.filter((filename) => filename.endsWith('.md'))
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
allErrors.push(...validateScheduler(cadence, roster[cadence] ?? [], rows, promptFiles));
|
||||
}
|
||||
|
||||
if (allErrors.length > 0) {
|
||||
console.error('Scheduler/roster drift detected:');
|
||||
for (const error of allErrors) {
|
||||
console.error(`- ${error}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('Scheduler tables, roster, and prompt filenames are in sync.');
|
||||
Reference in new issue
Block a user