diff --git a/.agents/skills/impeccable/scripts/context-signals.mjs b/.agents/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.agents/skills/impeccable/scripts/context-signals.mjs +++ b/.agents/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.agents/skills/impeccable/scripts/critique-storage.mjs b/.agents/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.agents/skills/impeccable/scripts/critique-storage.mjs +++ b/.agents/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.claude/skills/impeccable/scripts/context-signals.mjs b/.claude/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.claude/skills/impeccable/scripts/context-signals.mjs +++ b/.claude/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.claude/skills/impeccable/scripts/critique-storage.mjs b/.claude/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.claude/skills/impeccable/scripts/critique-storage.mjs +++ b/.claude/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.cursor/skills/impeccable/scripts/context-signals.mjs b/.cursor/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.cursor/skills/impeccable/scripts/context-signals.mjs +++ b/.cursor/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.cursor/skills/impeccable/scripts/critique-storage.mjs b/.cursor/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.cursor/skills/impeccable/scripts/critique-storage.mjs +++ b/.cursor/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.gemini/skills/impeccable/scripts/context-signals.mjs b/.gemini/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.gemini/skills/impeccable/scripts/context-signals.mjs +++ b/.gemini/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.gemini/skills/impeccable/scripts/critique-storage.mjs b/.gemini/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.gemini/skills/impeccable/scripts/critique-storage.mjs +++ b/.gemini/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.github/skills/impeccable/scripts/context-signals.mjs b/.github/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.github/skills/impeccable/scripts/context-signals.mjs +++ b/.github/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.github/skills/impeccable/scripts/critique-storage.mjs b/.github/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.github/skills/impeccable/scripts/critique-storage.mjs +++ b/.github/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.grok/skills/impeccable/scripts/context-signals.mjs b/.grok/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.grok/skills/impeccable/scripts/context-signals.mjs +++ b/.grok/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.grok/skills/impeccable/scripts/critique-storage.mjs b/.grok/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.grok/skills/impeccable/scripts/critique-storage.mjs +++ b/.grok/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.kiro/skills/impeccable/scripts/context-signals.mjs b/.kiro/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.kiro/skills/impeccable/scripts/context-signals.mjs +++ b/.kiro/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.kiro/skills/impeccable/scripts/critique-storage.mjs b/.kiro/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.kiro/skills/impeccable/scripts/critique-storage.mjs +++ b/.kiro/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.opencode/skills/impeccable/scripts/context-signals.mjs b/.opencode/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.opencode/skills/impeccable/scripts/context-signals.mjs +++ b/.opencode/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.opencode/skills/impeccable/scripts/critique-storage.mjs b/.opencode/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.opencode/skills/impeccable/scripts/critique-storage.mjs +++ b/.opencode/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.pi/skills/impeccable/scripts/context-signals.mjs b/.pi/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.pi/skills/impeccable/scripts/context-signals.mjs +++ b/.pi/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.pi/skills/impeccable/scripts/critique-storage.mjs b/.pi/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.pi/skills/impeccable/scripts/critique-storage.mjs +++ b/.pi/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.qoder/skills/impeccable/scripts/context-signals.mjs b/.qoder/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.qoder/skills/impeccable/scripts/context-signals.mjs +++ b/.qoder/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.qoder/skills/impeccable/scripts/critique-storage.mjs b/.qoder/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.qoder/skills/impeccable/scripts/critique-storage.mjs +++ b/.qoder/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.rovodev/skills/impeccable/scripts/context-signals.mjs b/.rovodev/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.rovodev/skills/impeccable/scripts/context-signals.mjs +++ b/.rovodev/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.rovodev/skills/impeccable/scripts/critique-storage.mjs b/.rovodev/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.rovodev/skills/impeccable/scripts/critique-storage.mjs +++ b/.rovodev/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.trae-cn/skills/impeccable/scripts/context-signals.mjs b/.trae-cn/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.trae-cn/skills/impeccable/scripts/context-signals.mjs +++ b/.trae-cn/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.trae-cn/skills/impeccable/scripts/critique-storage.mjs b/.trae-cn/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.trae-cn/skills/impeccable/scripts/critique-storage.mjs +++ b/.trae-cn/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.trae/skills/impeccable/scripts/context-signals.mjs b/.trae/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.trae/skills/impeccable/scripts/context-signals.mjs +++ b/.trae/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.trae/skills/impeccable/scripts/critique-storage.mjs b/.trae/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.trae/skills/impeccable/scripts/critique-storage.mjs +++ b/.trae/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/.vibe/skills/impeccable/scripts/context-signals.mjs b/.vibe/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/.vibe/skills/impeccable/scripts/context-signals.mjs +++ b/.vibe/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/.vibe/skills/impeccable/scripts/critique-storage.mjs b/.vibe/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/.vibe/skills/impeccable/scripts/critique-storage.mjs +++ b/.vibe/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); } diff --git a/plugin/skills/impeccable/scripts/context-signals.mjs b/plugin/skills/impeccable/scripts/context-signals.mjs index 743bb220a..e56214be1 100644 --- a/plugin/skills/impeccable/scripts/context-signals.mjs +++ b/plugin/skills/impeccable/scripts/context-signals.mjs @@ -22,7 +22,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import { loadContext, extractPlatform } from './context.mjs'; -import { getCritiqueDir } from './lib/impeccable-paths.mjs'; +import { readLatestSnapshotAcrossTargets } from './critique-storage.mjs'; /** Is there code here at all, or just context files / an empty repo? */ function hasCode(cwd) { @@ -34,23 +34,13 @@ function hasCode(cwd) { } /** - * The most recent critique snapshot across all targets. Filenames are - * timestamp-prefixed (`__.md`), so a lexical sort is chronological. - * Parses the small frontmatter for score + P0/P1 counts. + * Summarize the most recent critique snapshot across all targets. */ function latestCritique(cwd) { try { - const dir = getCritiqueDir(cwd); - if (!fs.existsSync(dir)) return null; - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort(); - if (!files.length) return null; - const newest = files[files.length - 1]; - const text = fs.readFileSync(path.join(dir, newest), 'utf-8'); - const front = text.split('---')[1] || ''; - const get = (k) => { - const m = front.match(new RegExp(`^${k}:\\s*(.+)$`, 'm')); - return m ? m[1].trim() : null; - }; + const latest = readLatestSnapshotAcrossTargets({ cwd }); + if (!latest) return null; + const get = (key) => latest.meta[key] ?? null; const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null; @@ -61,7 +51,7 @@ function latestCritique(cwd) { p0: num(get('p0')), p1: num(get('p1')), timestamp: get('timestamp'), - file: path.relative(cwd, path.join(dir, newest)), + file: path.relative(cwd, latest.path), }; } catch { return null; diff --git a/plugin/skills/impeccable/scripts/critique-storage.mjs b/plugin/skills/impeccable/scripts/critique-storage.mjs index a8b36b025..f23fded37 100644 --- a/plugin/skills/impeccable/scripts/critique-storage.mjs +++ b/plugin/skills/impeccable/scripts/critique-storage.mjs @@ -105,28 +105,37 @@ function parseFrontmatter(text) { } /** - * Return all snapshot files for `slug`, sorted oldest → newest. + * Return snapshot files matching `suffix`, sorted oldest → newest. */ -function listSnapshotsForSlug(slug, cwd) { +const SNAPSHOT_FILENAME = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z__.+\.md$/; + +function listSnapshots(suffix, cwd) { const dir = getCritiqueDir(cwd); if (!fs.existsSync(dir)) return []; - const suffix = `__${slug}.md`; return fs.readdirSync(dir) - .filter((f) => f.endsWith(suffix)) + .filter((f) => SNAPSHOT_FILENAME.test(f) && f.endsWith(suffix)) .sort() .map((f) => path.join(dir, f)); } +function readLatestSnapshotMatching(suffix, cwd) { + const filePath = listSnapshots(suffix, cwd).at(-1); + if (!filePath) return null; + const body = fs.readFileSync(filePath, 'utf-8'); + return { path: filePath, body, meta: parseFrontmatter(body) }; +} + /** * Return the most recent snapshot for `slug`, or null. Polish reads this * to find its fix backlog when the slug matches. */ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); - if (!all.length) return null; - const latest = all[all.length - 1]; - const body = fs.readFileSync(latest, 'utf-8'); - return { path: latest, body, meta: parseFrontmatter(body) }; + return readLatestSnapshotMatching(`__${slug}.md`, cwd); +} + +/** Return the most recent snapshot across all targets, or null. */ +export function readLatestSnapshotAcrossTargets({ cwd = process.cwd() } = {}) { + return readLatestSnapshotMatching('.md', cwd); } /** @@ -134,7 +143,7 @@ export function readLatestSnapshot(slug, { cwd = process.cwd() } = {}) { * Critique appends a one-line trend to its output using this. */ export function readTrend(slug, { limit = 5, cwd = process.cwd() } = {}) { - const all = listSnapshotsForSlug(slug, cwd); + const all = listSnapshots(`__${slug}.md`, cwd); const slice = all.slice(-limit); return slice.map((file) => parseFrontmatter(fs.readFileSync(file, 'utf-8'))); }