diff --git a/scripts/validate-scheduler-roster.mjs b/scripts/validate-scheduler-roster.mjs index 72a00eb..d26f410 100644 --- a/scripts/validate-scheduler-roster.mjs +++ b/scripts/validate-scheduler-roster.mjs @@ -1,4 +1,5 @@ import { readdir, readFile } from 'node:fs/promises'; +import { join } from 'node:path'; const CONFIG = { daily: { @@ -97,6 +98,44 @@ function validateScheduler(cadence, roster, rows, promptFiles) { return errors; } +async function listMarkdownFiles(dir) { + const entries = await readdir(dir, { withFileTypes: true }); + const files = []; + + for (const entry of entries) { + const fullPath = join(dir, entry.name); + if (entry.isDirectory()) { + files.push(...(await listMarkdownFiles(fullPath))); + continue; + } + + if (entry.isFile() && entry.name.endsWith('.md')) { + files.push(fullPath); + } + } + + return files; +} + +async function validateCanonicalPromptPaths() { + const errors = []; + const markdownFiles = await listMarkdownFiles('src/prompts'); + const invalidPathPattern = /src\/src\/(context|todo|decisions|test_logs)\b/; + + for (const file of markdownFiles) { + const content = await readFile(file, 'utf8'); + if (!invalidPathPattern.test(content)) { + continue; + } + + errors.push( + `[prompt-paths] ${file} contains invalid canonical path references using "src/src/..."; expected "src/..."`, + ); + } + + return errors; +} + const roster = JSON.parse(await readFile('src/prompts/roster.json', 'utf8')); const allErrors = []; @@ -111,6 +150,8 @@ for (const [cadence, cfg] of Object.entries(CONFIG)) { allErrors.push(...validateScheduler(cadence, roster[cadence] ?? [], rows, promptFiles)); } +allErrors.push(...(await validateCanonicalPromptPaths())); + if (allErrors.length > 0) { console.error('Scheduler/roster drift detected:'); for (const error of allErrors) { diff --git a/src/prompts/daily/scheduler-update-agent.md b/src/prompts/daily/scheduler-update-agent.md index 873f5bb..667b479 100644 --- a/src/prompts/daily/scheduler-update-agent.md +++ b/src/prompts/daily/scheduler-update-agent.md @@ -77,10 +77,10 @@ WORKFLOW 1. Preflight - Read `AGENTS.md` and `CLAUDE.md`. - Update persistent state files using repository conventions: - - `src/src/context/CONTEXT_.md` - - `src/src/todo/TODO_.md` - - `src/src/decisions/DECISIONS_.md` - - `src/src/test_logs/TEST_LOG_.md` + - `src/context/CONTEXT_.md` + - `src/todo/TODO_.md` + - `src/decisions/DECISIONS_.md` + - `src/test_logs/TEST_LOG_.md` - Store execution logs under `task-logs/daily/`. 2. Inventory — Daily prompts @@ -128,7 +128,7 @@ WORKFLOW 9. Document - Log additions/removals/renames in commit message. - - Update `src/src/test_logs/TEST_LOG_.md` with verification results. + - Update `src/test_logs/TEST_LOG_.md` with verification results. ─────────────────────────────────────────────────────────────────────────────── VERIFICATION @@ -161,7 +161,7 @@ FAILURE MODES - If a scheduler file or `src/prompts/roster.json` is missing/corrupt, open an issue and stop. Do not recreate from scratch. - If you cannot determine whether a rename occurred, treat as delete + add and - log ambiguity in `src/src/decisions/DECISIONS_.md`. + log ambiguity in `src/decisions/DECISIONS_.md`. - If scheduler roster table format no longer matches expected pattern, stop and open an issue rather than risking malformed edits.