Repository navigation
juniper-data-client v0.6.0 Release Notes
Release Date: 2026-10-10
Version: 0.6.0
Release Type: MINOR
Overview
juniper-data-client v0.6.0 rolls up the release-worthy changes accumulated on main since the last published release, generated by the Juniper release-train from this package's CHANGELOG.
Release Summary
- Release type: MINOR
- Primary focus: behavioural changes, bug fixes
- Breaking changes: YES
- Package:
juniper-data-clientv0.6.0
What's New
Changed
- BREAKING (contract):
validate_npz_contractcloses the W1.4 validator gaps and enforcesfloat32(juniper-ml
notes/JUNIPER_2026-10-03_JUNIPER-RECURRENCE_EQUITIES-END-TO-END-AUDIT-AND-DEVELOPMENT-PLAN.md
v1.3.0, item W1.4, findings F-P3 and F-S3). The audit found the advertised full-contract gate
partial:dtwas checked for shape, sign and a zero first column but not finiteness,
target_dt_*was ignored, and no dtype was enforced. Four rules join it. Each is
presence-conditional and raisesJuniperDataContractErrorwith a message naming the key and the
rule.dt_*must be finite, checked before the sign test, so-infis reported as non-finite
rather than as a negative gap and+inf/NaNno longer pass.target_dt_*, if present,
must be(W,), finite and>= 0.seq_lengths_*, if present, must be(W,), an integer
dtype, and in[1, L], whereLis the matchingX_*'s window length.X_*/y_*/
y_reg_*must befloat32in every partition present, on the 2-D path too, so the tabular
path is no longer "no further checks". Thefloat32rule applies the plan's recommended R2
pending the owner's ruling (the alternative is documented dtype tolerance). It compares the
scalar type, so a big-endian>f4array passes, and it deliberately does not reachdt,t,
target_dt, the masks,date,window_end_date,ticker_codeorticker_vocab, which the
producer emits in their own dtypes. A legacyX_full/y_fullpair is still neither required
nor checked. Stricter, so breaking for any caller that fed itfloat64features or targets.
Measured against what the consumers actually feed it
(util/ad-hoc/2026-10-05_w1_4_downstream_census_probe.py: 24 rows, 0 surprises): every offline
juniper-data generator, the juniper-data e2e test that runs this validator, juniper-canopy's
fake-vs-real agreement test and juniper-recurrence'ssynthetic_npz_arraysfixture all still
pass. Pins:tests/test_contract.py, with one test per new rejection, conforming three-partition
sequence and flat artifacts, and each new rule mutation-checked.
Fixed
- Two workflow comments still called
Sequence Safetyadvisory.sequence-safety.yml's
concurrency note andmain-verify.yml's header both described the per-PR screen as advisory.
It is a required context indata-client-rules. #198 corrected the workflow header and #230
the docs, but these two lines were missed. Found by the 2026-10-08 flood-3 follow-up sweep. ci.yml'snotify-downstreamjob reported a failed dispatch as success (#211). Its three
repository_dispatchcalls (data-client-updatedinto juniper-data, juniper-cascor and
juniper-canopy) were barecurl -X POST, and curl exits 0 on an HTTP error. A revoked or
under-scopedCROSS_REPO_DISPATCH_TOKEN(401, 403 or 404) therefore showed a green step, and the
downstream CI the job exists to trigger silently never ran. Each call is now
curl --fail-with-body --silent --show-error, as juniper-data'snotify-consumers.ymlalready
is. The second and third steps run even when an earlier one failed (!cancelled()), so one bad
target does not hide the others, and the job still fails. The token and the sha now reach the
shell throughenv:instead of being interpolated into the script, and the payload is built
withjq, into a variable first so a jq failure stops the step. It is byte-identical to the
old literal. Not closed:/dispatchesreturns 204 whether or not any workflow in the
target listens for the event type, so a renamed or missing listener still passes. All three
receivers declarerepository_dispatch: types: [data-client-updated]today, and each shows a
data-client-updatedrun from 2026-09-23. A check that the receiver started a run would catch
a missing listener (juniper-data#431 adds one to juniper-data's release sender); it is not
added here, and #213 tracks the receivers. A started run is not a tested client either:
juniper-data's and juniper-cascor's CI install this client from gitmain, so a dispatch run
that one of their own later pushes cancels is covered by the push run that cancelled it, while
juniper-canopy's CI has no git install of this client, so no run there tests the pushed one.lockfile-update.ymlcommitted the regenerated lockfile UNSIGNED, which can block the merge it
exists to enable. Therequired_signaturesruleset is~DEFAULT_BRANCH-scoped, so the plain
git commit+git pushtodependabot/pip/**succeeded and left an unsigned commit in the
branch's history. That is harmless under a squash merge — GitHub authors and signs the squash commit
itself — but this repo also allows merge commits and rebase merges, and both replay the original
commit ontomain, whererequired_signaturesrejects it. The step now goes through
createCommitOnBranch, which GitHub signs, matching juniper-cascor / juniper-data / juniper-canopy
and juniper-cascor-worker#180.CROSS_REPO_DISPATCH_TOKENstays the identity so the commit still
re-triggers CI, andexpectedHeadOidkeeps the compare-and-swap the old push had. The
no-lockfile-yet guard is preserved. Latent, never fired: run 34126070406 (2026-09-07) and every
earlier run found the lockfile already current and took the "no commit needed" branch.
Known Issues
None known at time of release.
Links
- Full Changelog
- Archive target:
notes/releases/RELEASE_NOTES_juniper-data-client_v0.6.0.md