diff options
Diffstat (limited to 'modules/test')
| -rw-r--r-- | modules/test/test-predictor-accuracy.js | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/modules/test/test-predictor-accuracy.js b/modules/test/test-predictor-accuracy.js index 1a79167..3688b03 100644 --- a/modules/test/test-predictor-accuracy.js +++ b/modules/test/test-predictor-accuracy.js @@ -149,7 +149,7 @@ function ok(name, cond, detail) { p.notePrediction('read the logs', 'test'); p.recordResult(p._extractFeatures('read the logs'), 0.5, 1, true, { task: 'read the logs' }); const rec = p._dataPoints[p._dataPoints.length - 1]; - ok('K1 errorPct capped at 500%', rec.errorPct <= 5, 'errorPct=' + rec.errorPct); + ok('K1 errorPct is stored raw', rec.errorPct > 5, 'errorPct=' + rec.errorPct); } // L. a tool/loop prediction is never consumed by the similarity fallback @@ -205,5 +205,47 @@ function ok(name, cond, detail) { 'total=' + p._accuracy.total + ' pending=' + p._pending.length); } + +// Q. an aborted 0.079 s run must not drive the next prediction to zero (§5 point 1→2) +{ + const { p } = mk(); + const task = 'paste a 2158 char status report'; + p.notePrediction(task, 'loop'); + p.recordResult(p._extractFeatures(task), 0.079, 1, true, { task }); + const next = p.notePrediction(task, 'loop'); + ok('Q1 prediction is never 0 s', next.predictedDuration >= 1, 'pred=' + next.predictedDuration); + ok('Q2 the aborted run is marked unusable', p._dataPoints[0].usable === false); + ok('Q3 it never trains _findSimilar', p._findSimilar(p._extractFeatures(task)).length === 0); +} + +// R. the persisted field is a SUM and the display divides by the paired count +{ + const { p, out, term } = mk(true); + for (let i = 0; i < 2; i++) { + const task = 'read the logs'; + p.notePrediction(task, 'loop'); + p.recordResult(p._extractFeatures(task), 20, 2, true, { task }); // 15 s predicted vs 20 s observed + } + p._saveNow(); + const blob = JSON.parse(term.fs.readFile('/system/metrics/predictor.json')); + ok('R1 stored accumulator is a sum and is named errorSum', typeof blob.errorSum === 'number' && !('mape' in blob), + JSON.stringify(Object.keys(blob))); + out.length = 0; p.showStatus(); + const line = out.find(l => l.includes('Accuracy')) || ''; + ok('R2 display shows the mean with its sample count', /Accuracy: \d+% \(2\/2 paired\) · mean error \d+%/.test(line), line.trim()); +} + +// S. a floored prediction is consumed but not scored as error (§5 defect C) +{ + const { p } = mk(); + const pred = p.notePrediction('read the logs', 'test'); + p._pending[0].floored = true; + p._pending[0].predictedDuration = 1; + p.recordResult(p._extractFeatures('read the logs'), 54.7, 2, true, { task: 'read the logs' }); + ok('S1 floored prediction does not enter accuracy', p._accuracy.total === 0, 'total=' + p._accuracy.total); + ok('S2 it is still recorded and marked unscored', p._dataPoints[0].scored === false); + ok('S3 pending consumed', p._pending.length === 0); +} + console.log(passes + '/' + (passes + fails) + ' PASS'); process.exit(fails ? 1 : 0); |