From 357f358050050acb36da3d418fe11e6e8f852b6b Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Tue, 11 Aug 2026 13:00:31 -0400 Subject: [PATCH] Reject empty critique metrics Treat empty and whitespace-only snapshot values as missing so malformed frontmatter cannot reintroduce plausible zeroes. Prepared with AI assistance under maintainer pbakaus's standing automation authorization. --- skill/scripts/context-signals.mjs | 2 +- tests/context-signals.test.mjs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/skill/scripts/context-signals.mjs b/skill/scripts/context-signals.mjs index f6b133365..c307a1ea9 100644 --- a/skill/scripts/context-signals.mjs +++ b/skill/scripts/context-signals.mjs @@ -42,7 +42,7 @@ function latestCritique(cwd) { if (!latest) return null; const get = (key) => latest.meta[key] ?? null; const num = (v) => { - if (v == null) return null; + if (v == null || (typeof v === 'string' && v.trim() === '')) return null; const n = Number(v); return Number.isFinite(n) ? n : null; }; diff --git a/tests/context-signals.test.mjs b/tests/context-signals.test.mjs index 3594fa313..8766abe82 100644 --- a/tests/context-signals.test.mjs +++ b/tests/context-signals.test.mjs @@ -94,6 +94,15 @@ describe('gatherSignals', () => { assert.equal(s.critique.latest.p1, null); }); + it('reports empty and invalid critique metrics as null', async () => { + write('.impeccable/critique/2026-05-02T10-00-00Z__pricing.md', + '---\nslug: pricing\ntotal_score: \np0_count: \np1_count: nope\ntimestamp: 2026-05-02T10-00-00Z\n---\nbody\n'); + const s = await gatherSignals(scratch); + assert.equal(s.critique.latest.score, null); + assert.equal(s.critique.latest.p0, null); + assert.equal(s.critique.latest.p1, null); + }); + it('reads the newest critique snapshot across target slugs', async () => { write('.impeccable/critique/2026-05-01T10-00-00Z__home.md', '---\nslug: home\nscore: 6\np0: 1\np1: 3\ntimestamp: 2026-05-01T10-00-00Z\n---\nbody\n');