diff --git a/skill/scripts/context-signals.mjs b/skill/scripts/context-signals.mjs index e56214be1..c307a1ea9 100644 --- a/skill/scripts/context-signals.mjs +++ b/skill/scripts/context-signals.mjs @@ -42,14 +42,15 @@ function latestCritique(cwd) { if (!latest) return null; const get = (key) => latest.meta[key] ?? null; const num = (v) => { + if (v == null || (typeof v === 'string' && v.trim() === '')) return null; const n = Number(v); return Number.isFinite(n) ? n : null; }; return { slug: get('slug'), - score: num(get('score')), - p0: num(get('p0')), - p1: num(get('p1')), + score: num(get('total_score') ?? get('score')), + p0: num(get('p0_count') ?? get('p0')), + p1: num(get('p1_count') ?? get('p1')), timestamp: get('timestamp'), file: path.relative(cwd, latest.path), }; diff --git a/tests/context-signals.test.mjs b/tests/context-signals.test.mjs index 5480496a3..8766abe82 100644 --- a/tests/context-signals.test.mjs +++ b/tests/context-signals.test.mjs @@ -76,6 +76,33 @@ describe('gatherSignals', () => { assert.equal(s.critique.latest.slug, 'home'); }); + it('reads the documented critique snapshot metadata keys', async () => { + write('.impeccable/critique/2026-05-02T10-00-00Z__pricing.md', + '---\nslug: pricing\ntotal_score: 24\np0_count: 2\np1_count: 5\ntimestamp: 2026-05-02T10-00-00Z\n---\nbody\n'); + const s = await gatherSignals(scratch); + assert.equal(s.critique.latest.score, 24); + assert.equal(s.critique.latest.p0, 2); + assert.equal(s.critique.latest.p1, 5); + }); + + it('reports missing critique metrics as null', async () => { + write('.impeccable/critique/2026-05-02T10-00-00Z__pricing.md', + '---\nslug: pricing\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('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');