flowrs-engine/crates/flowrs-record/PROVENANCE.md
flowRS fd958c0547 flowRS engine, cut from flowRS 3451b065
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 19:04:39 -05:00

105 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Provenance of flowrs-record
Everything in this crate is written for flowRS and licensed MIT OR Apache-2.0, apart from
Howard Hinnant's public-domain date algorithms (see `NOTICE`). Per-file origins are listed in
`tools/runtime-licence.tsv`. This file records where the record formats' facts come from.
## Re-cited to primary sources (2026-10-27)
The licence audit found two files that had read interoperability facts from GPL projects:
- `src/stdf.rs` took its field order from pystdf (GPL-2.0);
- `src/hardpy.rs` took its key names and enum strings from HardPy's schema module (GPL-3.0).
Facts are not copyrightable, but the porting policy wants them cited to a primary source. Each
file was compared with the sources below, not with the GPL projects.
### `src/stdf.rs`: the STDF V4 specification
| Source | Licence | Checked |
|---|---|---|
| Teradyne, *Standard Test Data Format (STDF) Specification, Version 4* (FrameMaker edition of 1999-07-06, 103 pages; read from the Internet Archive's copy of `kanwoda.com/wp-content/uploads/2015/05/std-spec.pdf`) | Teradyne documentation; facts only | See below |
| *STDF V4-2007 Specification* (from roos.com) | documentation; facts only | The table of record types and sub-types |
The following match the specification:
- the record header (`REC_LEN` U*2, data bytes only, then `REC_TYP` and `REC_SUB`);
- every record's type and sub-type: FAR 0/10, MIR 1/10, MRR 1/20, PCR 1/30, HBR 1/40, SBR 1/50,
PIR 5/10, PRR 5/20 and PTR 15/10;
- the field order of every record the writer emits and the reader decodes, field by field
against the specification's tables;
- `CPU_TYPE` 2 (little-endian), `STDF_VER` 4, and the missing-data values (`BURN_TIM` 65535,
`X_COORD`/`Y_COORD` −32768, `TEST_T` 0, the space for C*1);
- `TEST_FLG` bit 7 (test failed), `PART_FLG` bit 3 (part failed), `HBIN_PF`/`SBIN_PF` `P`/`F`;
- the rule that only optional fields at the end of a record may be left off.
The writer builds each record with one small encoder per STDF data type, in the
specification's field order. It is not a table of field descriptors, which is how pystdf
describes records.
**Deviation found and fixed (2026-10-27).** The writer used to mark an absent low (or high)
test limit with `OPT_FLAG` bit 4 (or 5), and the reader took that bit to mean "absent". It
also wrote the reserved bit 1 as 0. The specification's PTR field description says:
- bit 1 is "reserved for future used and must be 1";
- bit 4 means "LO_LIMIT and LLM_SCAL are invalid. The default values set for these fields in
the first PTR with this test number will be used", and bit 5 the same for the high limit;
- "No Low Limit for this test" is bit 6, and "No High Limit" bit 7.
The writer now sets bit 1 always, bits 2 and 3 (no LO_SPEC or HI_SPEC is written), and bit 6 or
7 for an absent limit. It never sets bits 4 or 5: each PTR it writes is the first for its test
number and carries its own limits. A PTR's `OPT_FLAG` is therefore 0x0E with both limits, 0x8E
with only a low limit, 0x4E with only a high limit, and 0xCE with none.
The reader follows the specification too. A field after `ALARM_ID` that a PTR leaves out, or
that bit 4 or 5 marks invalid, takes the value of the first PTR with the same test number.
Bits 6 and 7 mean the test has no such limit. Files flowRS wrote before the fix still read
correctly: bit 4 or 5 sat on the first PTR for its test, which has nothing to inherit, so the
limit stays absent.
The unit tests and `tools/verify_stdf.py` pin the exact bytes and cite the field description.
`tools/mutate-stdf.sh` checks that the tests catch each wrong bit.
pystdf (GPL-2.0) is only run out of process, as an independent reader of what the writer
emits (`tools/verify_stdf.py`).
### `src/hardpy.rs`: HardPy's public documentation, as an interoperability format
| Source | Licence | Checked |
|---|---|---|
| HardPy documentation, *Database* (`everypinio.github.io/hardpy/documentation/database/`, read 2026-10-27) | Documentation of a GPL-3.0 project; names only | Listed below |
| HardPy documentation, *pytest-hardpy* API (`everypinio.github.io/hardpy/documentation/pytest_hardpy/`) | as above | Listed below |
The *Database* page gives:
- the report keys: `_id`, `_rev`, `name`, `status`, `start_time` and `stop_time` (Unix
seconds), `dut`, `test_stand`, `process`, `modules`, `user`, `batch_serial_number`,
`caused_dut_failure_id`, `error_code` and `artifact`;
- the fields of `dut` (`name`, `type`, `serial_number`, `part_number`, `revision`,
`sub_units`, `info`), of `test_stand` (`hw_id`, `name`, `revision`, `timezone`, `location`,
`number`, `instruments`, `info`) and of `process` (`name`, `number`, `info`);
- a module's and a case's keys;
- a numeric measurement's keys (`type` `numeric`, `value`, `name`, `unit`, `operation`,
`comparison_value`, `lower_limit`, `upper_limit`, `result`);
- the statuses `passed`, `failed`, `skipped` and `stopped`.
The API page names the comparison operations and gives the role of `lower_limit`,
`upper_limit` and `comparison_value`.
**Flagged: three names the documentation does not settle.** The module writes them as an
earlier reading of HardPy's schema module found them:
- operations in lower case (`gtlt`), where the documentation's example shows `"GTLT"`;
- the status `error`;
- a case's `attempt` key.
They should be checked by running HardPy as a black-box oracle: build a report with HardPy's
public API, serialise it, and compare. That was not done in this session, because running
HardPy here was not approved.
### `src/opentap.rs`: names only
`ResultTable` (a name and an array of `ResultColumn`), `ResultColumn` (`Name`, `Data`) and the
`Verdict` names (`NotSet`, `Pass`, `Inconclusive`, `Fail`, `Aborted`, `Error`) are cited from
OpenTAP's public API reference and documentation (`doc.opentap.io`, 9.35). No OpenTAP code
(MPL-2.0) is in this crate.