dataforth(datasheet): wire DSCA33/45 Hoffman-mined templates (gated; accuracy-data WIP)
Per the 5070 handoff (DSCA33-45-HOFFMAN-RECOVERY): the lost DSCA33/45 specs are
recoverable from Hoffman, not John. Wired the mined dsca33-45-templates.json (56
models) into the renderer:
- datasheet-exact.js: load DSCA3345_TEMPLATES; for family DSCA, the Hoffman-mined
template takes PRECEDENCE over the stale staged-extraction entry (which shadowed 25
models with accOut "?"/no accHeader). Emit the verbatim 2-line accHeader for these
families (Vin (mVAC)/Iin (AAC)/Frequency (Hz), Output (VDC)/(mADC)). Per-model
`validated` GATE: a DSCA33/45 model renders only after byte-matching its Hoffman
original; until then it returns null (skipped) so an unverified render can never
overwrite a pristine live original. DSCA_VALIDATE_MODE env opens the gate for the
validation harness only. Exposed rendersWithoutSpecs().
- render-datasheet.js: allow a null-specs render for DSCA33/45 (their spec files were
lost; template-driven) instead of bailing on missing specs.
- derive-dsca-slotmaps.js: DSCA_TPL env to target the 3345 templates; derived 43 slot
maps into them (22 models need none, 8 DSCA33 still below threshold).
- validate-dsca3345.js (new): renders each model's _srcSerial, fetches the live
Hoffman original (GET TestReportDataFiles/{serial}, deployed uploader token — no
vault needed), content-normalized compare; --apply marks validated.
STATUS: gate is CLOSED — 0 models validated, all DSCA33/45 still render null, nothing
published, no risk. Final-Test block + accuracy headers now byte-match the Hoffman
originals for all 56 models; the remaining blocker is accuracy-DATA numeric quirks that
must match to pass the gate:
- DSCA33 calc column stored in A but displayed in mADC (x1000); measured stored in
mA (not scaled) — an original-software unit quirk.
- sign conventions differ per layout (DSCA33 stim/calc/meas unsigned, error signed;
DSCA45 stim unsigned, calc/meas/error signed).
- DSCA45 frequency-input stim formatting.
These need per-layout reverse-engineering against the originals (the validation harness
is the oracle). 8 DSCA33 models (DSCA33-02/03/03A/04/04A/05/05A/1642) also lack a slot
map (below threshold). DSCA33-1948 + DSCA45-1746 (24 units) have no Hoffman original.
Cleanups: deleted superseded memory project_dsca33_45_spec_gap; struck the obsolete
"ask John" TODO 2 from the handoff note.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* In-memory equivalent of what export-datasheets.js writes to
|
||||
* X:\For_Web\<SN>.TXT. Lets upload-to-api.js POST directly to Hoffman's API
|
||||
* from DB state without a filesystem intermediate.
|
||||
*
|
||||
* Returns a string (datasheet text) or null if the record cannot be rendered
|
||||
* (no specs for the model, no raw_data for VASLOG_ENG, etc.).
|
||||
*/
|
||||
const { loadAllSpecs, getSpecs } = require('../parsers/spec-reader');
|
||||
const { generateExactDatasheet, rendersWithoutSpecs } = require('../templates/datasheet-exact');
|
||||
|
||||
let _specMap = null;
|
||||
function specs() {
|
||||
if (_specMap === null) _specMap = loadAllSpecs();
|
||||
return _specMap;
|
||||
}
|
||||
|
||||
function renderContent(record) {
|
||||
if (record.log_type === 'VASLOG_ENG') {
|
||||
return record.raw_data || null;
|
||||
}
|
||||
const modelSpecs = getSpecs(specs(), record.model_number);
|
||||
// DSCA33/45 lost their spec files in the wipe but render from the Hoffman-mined
|
||||
// templates (template-driven names/specs + verbatim accuracy header), so allow a
|
||||
// null-specs render for them. generateExactDatasheet still gates on per-model
|
||||
// validation and returns null until the model is verified.
|
||||
if (!modelSpecs && !rendersWithoutSpecs(record.model_number)) return null;
|
||||
return generateExactDatasheet(record, modelSpecs) || null;
|
||||
}
|
||||
|
||||
module.exports = { renderContent };
|
||||
@@ -18,6 +18,18 @@ try {
|
||||
DSCA_TEMPLATES = {};
|
||||
}
|
||||
|
||||
// DSCA33/DSCA45 templates recovered from the Hoffman API (their main spec files were
|
||||
// lost in the wipe). Superset schema: also carries a verbatim 2-line `accHeader`, a
|
||||
// `_srcSerial` validation oracle, and a `validated` gate flag. A model renders ONLY
|
||||
// after its render byte-matches the Hoffman original (validated:true) — until then it
|
||||
// stays null/skipped so the pipeline never overwrites a pristine original.
|
||||
let DSCA3345_TEMPLATES = {};
|
||||
try {
|
||||
DSCA3345_TEMPLATES = require('../dsca33-45-templates.json');
|
||||
} catch (e) {
|
||||
DSCA3345_TEMPLATES = {};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// DATA LINES: parameter names and units per family
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -552,13 +564,24 @@ function generateExactDatasheet(record, specs) {
|
||||
return generateSCMVASDatasheet(record);
|
||||
}
|
||||
|
||||
// DSCA STAGE 2: the per-model staged template is the authoritative Final-Test
|
||||
// layout (names + specs + accuracy output label). No template means no staged
|
||||
// original was available -> do not guess the layout; skip this cert.
|
||||
// DSCA: the per-model template is the authoritative Final-Test layout (names +
|
||||
// specs + accuracy label). Source is the staged-original set (dsca-templates) or
|
||||
// the Hoffman-mined set (dsca33-45-templates) for the families whose specs were
|
||||
// lost. No template -> do not guess; skip this cert.
|
||||
const dscaKey = (record.model_number || '').trim();
|
||||
// Hoffman-mined templates take PRECEDENCE: DSCA33/45 were also captured by the
|
||||
// STAGE 1 staged extractor (sometimes with accOut "?" and no accHeader), and that
|
||||
// stale entry must not shadow the authoritative Hoffman-mined one.
|
||||
const dscaTpl = (family === 'DSCA')
|
||||
? (DSCA_TEMPLATES[(record.model_number || '').trim()] || null)
|
||||
? (DSCA3345_TEMPLATES[dscaKey] || DSCA_TEMPLATES[dscaKey] || null)
|
||||
: null;
|
||||
if (family === 'DSCA' && !dscaTpl) return null;
|
||||
// Hoffman-mined DSCA33/45 render only once the model is byte-validated against its
|
||||
// Hoffman original — otherwise stay null so an unverified render can't overwrite a
|
||||
// live original. The validation harness sets DSCA_VALIDATE_MODE to render
|
||||
// unvalidated models for the byte-compare; the live service never sets it.
|
||||
if (family === 'DSCA' && DSCA3345_TEMPLATES[dscaKey] && !DSCA3345_TEMPLATES[dscaKey].validated
|
||||
&& !process.env.DSCA_VALIDATE_MODE) return null;
|
||||
|
||||
const parsed = (family === 'SCM7B')
|
||||
? parse7BRawData(record.raw_data)
|
||||
@@ -614,6 +637,14 @@ function generateExactDatasheet(record, specs) {
|
||||
} else {
|
||||
lines.push(' ACCURACY TEST');
|
||||
lines.push('');
|
||||
if (dscaTpl && Array.isArray(dscaTpl.accHeader) && dscaTpl.accHeader.length >= 2) {
|
||||
// DSCA33/45 (Hoffman-mined): the accuracy header carries model-specific tokens
|
||||
// the sensor-type logic can't synthesize (Vin (mVAC), Iin (AAC), Frequency (Hz),
|
||||
// Output (VDC)/(mADC)). Emit the verbatim 2-line header from the original.
|
||||
lines.push(dscaTpl.accHeader[0]);
|
||||
lines.push(dscaTpl.accHeader[1]);
|
||||
lines.push(TAB5 + '-'.repeat(10) + ' ' + '-'.repeat(11) + ' ' + '-'.repeat(11) + ' ' + '-'.repeat(10) + ' ' + '-'.repeat(8));
|
||||
} else {
|
||||
lines.push(' Calculated Measured');
|
||||
|
||||
// Input column header based on sensor type
|
||||
@@ -631,6 +662,7 @@ function generateExactDatasheet(record, specs) {
|
||||
const accSep = (family === 'DSCA') ? '-' : '=';
|
||||
lines.push(' ' + inputHeader + ' ' + accOut + ' ' + accOut + '* Error (%) Status');
|
||||
lines.push(TAB5 + accSep.repeat(10) + ' ' + accSep.repeat(10) + ' ' + accSep.repeat(10) + ' ' + accSep.repeat(9) + ' ' + accSep.repeat(8));
|
||||
}
|
||||
|
||||
for (const point of parsed.accuracy) {
|
||||
lines.push(formatAccuracyLine(point, sensorNum, maxIn));
|
||||
@@ -1024,11 +1056,21 @@ function generateSCMVASDatasheet(record) {
|
||||
return lines.join('\r\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the model renders from a template that does NOT require spec-reader specs
|
||||
* (the Hoffman-mined DSCA33/45 set). Lets render-datasheet.js skip the missing-specs
|
||||
* bail for these. (Still gated on per-model `validated` inside generateExactDatasheet.)
|
||||
*/
|
||||
function rendersWithoutSpecs(modelNumber) {
|
||||
return !!DSCA3345_TEMPLATES[(modelNumber || '').trim()];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateExactDatasheet,
|
||||
generateSCMVASDatasheet,
|
||||
extractSCMVASAccuracy,
|
||||
parseRawData,
|
||||
parse7BRawData,
|
||||
rendersWithoutSpecs,
|
||||
DATA_LINES,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user