ULC v1.4.0
ulc CLI v1.4.0
Download a single-file binary for your platform below. See CHANGELOG.md
at the tag for what landed in this release.
Product lifecycle and warranty-basis fields. Three commercial-lifecycle facts gain structured homes: superseded_by names the successor product of a superseded record, discontinued_at carries the effective end-of-availability date, and shared_warranty.term_basis states the event a warranty term runs from, beside a new hashed shared_warranty.conditions_document reference. Every addition is an optional field: no required set changes, nothing is removed or narrowed, no conformance grade or achievement state moves, and the generated index is untouched, so the builder version does not bump and no stored record needs re-stamping. Every example record and golden file is byte-identical.
For consumers
Nothing to do. Records that omit the new fields validate and grade exactly as before; records that carry them validate against the new definitions. The new fields are tracked, not graded: they gate no conformance tier and change no computed value. discontinued_at is a format: date field, so it joins the dates that schema validation asserts as of 1.3.0: a value that is not an ISO 8601 YYYY-MM-DD date fails validation at /discontinued_at.
The admission rule behind the lifecycle pair is worth stating, because it governs what ULC will and will not carry. A ULC record pins its source documents by content hash and is published as a point-in-time artifact, so a value that changes while the product stays the same goes stale in a record that was correct when it was written. ULC therefore carries facts keyed by the product, and admits a commercial fact only when it is settled: recorded once, when the underlying event is fixed, so it can appear on a record but does not drift the way volatile commercial data does. A supersession pointer and a settled discontinuation date qualify. Lead times, stock, and prices do not, and stay out. Precedent: GDSN carries discontinuedDateTime inside the master trade-item record.
superseded_byresolves a long-standing incoherence:record_statuscould saysuperseded, documented as "replaced by a newer SKU", while no slot named the SKU. The pointer names the successor bycatalog_number(the successor order code, the SKU-precise slot), bycatalog_model(the successor family model, when the exact order code is not yet assigned), by ULCrecord_idonce the successor record is published, or several of these together, and can pin the exact successor record revision withrecord_sha256.discontinued_atis the effective end-of-availability date, distinct fromrecord_status_as_of(when the status was last verified).shared_warranty.term_basis(invoice,shipment,installation,energization) states the event the warranty term runs from; identical term lengths differ materially by basis.shared_warranty.conditions_documentreferences the published warranty-conditions document by filename and content hash, with its revision label and date when the document states them, so exclusions and conditional extensions travel with the headline number. The free-textconditions_referenceis deprecated in its favor and is scheduled for removal at v2.0.0; it remains valid throughout the 1.x line. The deprecation is machine-readable: the field carries the JSON Schemadeprecatedannotation, which changes no validation result.
The new commercial_terms_pdf token names a document, not its contents: a record referencing one asserts that the document with that hash existed on the referenced revision date, and never that the numbers inside it are current.
No example record changes: the repository's real-data rule forbids fabricating lifecycle facts, so shipped examples gain the new fields only when their manufacturers publish the underlying data.
Schema
- New top-level optional fields
superseded_by(via the new$defs/SupersessionReference) anddiscontinued_at.SupersessionReferencerequires at least one ofrecord_id,catalog_number, orcatalog_model, andrecord_sha256requiresrecord_id; the constraints live entirely inside the new definition, so no previously-valid record is affected. product_family.shared_warrantygainsterm_basisandconditions_document;conditions_referencecarries thedeprecatedannotation and a deprecation notice in its description, with its type unchanged.- The
deprecatedannotation also lands on the taxonomy's legacy cutoff classification, whose description has marked it deprecated since it shipped; no validation behavior changes. - New taxonomy enum
WarrantyTermBasiswith four tokens. It is descriptive vocabulary: it gates no conformance tier and feeds no rubric row. - New
SourceFileTypeandProvenanceSourcetokencommercial_terms_pdffor manufacturer-published commercial-terms documents carried as hashed source files; the two enums stay synchronized by design.
Validator
ulc from-sheetgains records-sheet columns for the new fields (superseded_by_record_id,superseded_by_record_sha256,superseded_by_catalog_number,superseded_by_catalog_model,discontinued_at,warranty_term_basis) and the path-input columnwarranty_conditions_file(hashed intoconditions_document, with__revision_labeland__revision_dateoverride columns). The previously uncolumnedwarranty_term_yearsandwarranty_scopegain columns in the same pass; both schema fields already existed. The deprecatedconditions_referencegets no column by design.ulc from-sheetnow stampsulc_version: "1.4.0"by default on converted records (the records-sheetulc_versioncolumn still overrides), aligning the default with the specification version whose fields the converter now authors. This is the one output change for existing workbooks. The two new date columns,discontinued_atandwarranty_conditions_file__revision_date, feedformat: datefields, so the rule in place since 1.3.0 applies to them: author dates as ISOYYYY-MM-DDtext, or validation rejects the record before it is written.- The byte-verification walk covers the new
product_family.shared_warranty.conditions_documentsite with the default policy: a local hash mismatch is an error, a locally absent file is informational. The walk's site registry, introduced in 1.3.0, gains the new site, and the validate help text and validator README name it in their default-site lists.
Docs
docs/authoring-patterns.md: the record-description section gains the lifecycle-facts paragraph, the cross-referencing section gains the supersession-pointer entry, and theproduct_familyprimitives entry names the warranty additions.templates/workbook/README.md: the records-sheet row of the sheet table names the lifecycle and warranty columns, with a note on settingrecord_statuswhen authoring a supersession.templates/README.md: the authoring-paths pointer now matches the verified-by-construction wording of the section it links to.tools/validator/internal/sheet/DESIGN.md: the path-input column enumeration gainsrecords.warranty_conditions_file, and the records-sheet field list reflects the new default version stamp.tools/validator/README.md: the hash-verification bullet's default-site list gains the warranty-conditions document.schema/README.md: the See also pointers now name the documents that exist, and the validation note states that the reference validator asserts declared string formats while a generic Draft 2020-12 validator treats them as annotations.README.md: the current-release version line, and the interoperability notes state how the reference validator's format assertion relates to a generic Draft 2020-12 validator.ROADMAP.md: the active-version heading and narrative, and the deferred-work list gains the scheduled v2.0.0 removal ofconditions_reference, the multi-leg warranty item, and the format-assertion conformance statement.