Iterated the convergence against the live Hoffman originals (no DSCA regression — DSCA33/45
held at 54/56, staged-92 render):
- rendersWithoutSpecs() now covers the mined 8B/5B (54 lacked spec files, same wipe gap as
DSCA33/45) so they render via the template path instead of the missing-specs bail.
- Accuracy formatter unified + driven by units parsed from the accHeader (the miner's accOut
is "?" for Iout models): output mA/mV -> x1000 on calc/meas; input mV/uV -> x1000 on stim;
temperature input -> 2dp; std/freq signed, AC unsigned; Math.fround throughout.
- splitSpecUnit now splits after the last number, so multi-word units survive
("< 17 uA RMS" -> unit "uA RMS", not "RMS").
- Verbatim "Model:" name captured per model (8B/5B prefix inconsistently: "SCM5B49-03" but
"5B45-03D") and rendered directly.
Result: 69/136 validated and marked (24 8B, 21 SCM5B via the template path; 24 SCM7B already
correct via the unchanged legacy 7B path). 67 remain (gated null, safe): 12 need slotMaps the
oracle couldn't derive; the rest are family-divergent tail — 8B/5B Final-Test drops the sign on
negative measured values (opposite of DSCA's keep-sign) needing family-specific measured
formatting, plus per-model "Packing Check List" footer variants. enrich-8b5bscm.js now also
captures modelName.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
2.6 KiB
JavaScript
33 lines
2.6 KiB
JavaScript
// Enrich 8b5bscm-templates.json: capture each model's verbatim Final-Test HEADER line
|
|
// (the "Parameter ... Measured Value[*] ... Specification ... Status" line) from its
|
|
// _srcSerial Hoffman original, since 8B/5B use two different header schemes (legacy
|
|
// "Measured Value" vs DSCA-style "Measured Value*"). Stored as `ftHeader`. --apply writes.
|
|
const fs = require('fs'), https = require('https');
|
|
const TPL = './8b5bscm-templates.json';
|
|
const c = JSON.parse(fs.readFileSync('C:\\ProgramData\\dataforth-uploader\\credentials.json', 'utf8'));
|
|
const APPLY = process.argv.includes('--apply');
|
|
function req(m, uri, h, b) { return new Promise((res, rej) => { const u = new URL(uri); const r = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: m, headers: h, timeout: 30000 }, x => { let d = ''; x.on('data', c => d += c); x.on('end', () => { try { res(JSON.parse(d)); } catch { res({ _raw: d }); } }); }); r.on('error', rej); if (b) r.write(b); r.end(); }); }
|
|
(async () => {
|
|
const tpl = JSON.parse(fs.readFileSync(TPL, 'utf8'));
|
|
const form = Object.entries({ grant_type: 'client_credentials', client_id: c.CF_CLIENT_ID, client_secret: c.CF_CLIENT_SECRET, scope: c.CF_SCOPE }).map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v)).join('&');
|
|
const t = (await req('POST', c.CF_TOKEN_URL, { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(form) }, form)).access_token;
|
|
let done = 0; const schemes = {};
|
|
for (const m of Object.keys(tpl)) {
|
|
const sn = tpl[m]._srcSerial; if (!sn) continue;
|
|
const g = await req('GET', c.CF_API_BASE + '/api/v1/TestReportDataFiles/' + encodeURIComponent(sn), { Authorization: 'Bearer ' + t });
|
|
if (!g.Content) continue;
|
|
const L = g.Content.replace(/\r/g, '').split('\n');
|
|
const fi = L.findIndex(l => /FINAL TEST RESULTS/.test(l)); if (fi < 0) continue;
|
|
const hi = L.findIndex((l, i) => i > fi && /Parameter\s+Measured/.test(l)); if (hi < 0) continue;
|
|
tpl[m].ftHeader = L[hi];
|
|
const mn = (g.Content.match(/^\s*Model:\s*(.+?)\s*$/m) || [])[1];
|
|
if (mn) tpl[m].modelName = mn;
|
|
const star = /Measured Value\*/.test(L[hi]) ? 'star' : 'plain';
|
|
schemes[star] = (schemes[star] || 0) + 1;
|
|
done++;
|
|
}
|
|
console.log('captured ftHeader for ' + done + ' models; header schemes: ' + JSON.stringify(schemes));
|
|
if (APPLY) { fs.writeFileSync(TPL, JSON.stringify(tpl)); console.log('[APPLY] wrote ' + TPL); }
|
|
else console.log('(dry run — pass --apply)');
|
|
})().catch(e => { console.error('ERR', e.message); process.exit(1); });
|