Repository navigation
sdk-sync: API 2.0.0+ffb34b7 → sdk-java (minor) - #103
marketdata-sdk-sync[bot] wants to merge 1 commit into
Conversation
tests: Added tests for the `dte` chain-filter type change (int -> string, forms: single value, comma list, closed range, comparison) against a new sealed `DteFilter` type (not yet implemented) added as a new permitted subtype of `ExpirationFilter`, reused alongside the existing `StrikeFilter.Operator`. Unit tests in OptionsResourceTest.java: 3 wire tests (one per new form: `dte=15,30,45`, `dte=0-45`, `dte=%3E%3D30`) plus 8 validation tests on the new factories (empty list, non-negative, max 36500, min<=max). The existing `ExpirationFilter.dte(int)` single-value test and method are untouched — it keeps its current error behavior and needs no probe since nothing existing changes. Added 4 live integration tests in OptionsIntegrationTest.java, one per form, each built to fail against the unfiltered (front-month-only) answer. No compatibility probe written: the delta is purely additive.
implement: Added `DteFilter` (new sealed permitted subtype of `ExpirationFilter`) for the API's dte type change: `values(int...)` (comma list), `range(int,int)` (closed, inclusive), `comparison(StrikeFilter.Operator,int)` — reusing StrikeFilter's existing operator syntax/type. `ExpirationFilter.dte(int)` is untouched, still the single-value form. `OptionsResource.applyExpirationFilter` renders the three new wire forms.
Docs/examples: updated — one line each per checklist item below.
1. docs/options/chain.md and OptionsAdvancedExample.java now show all three new forms with runnable examples.
2. DteFilter's interface and its three static factories carry javadoc; records follow the existing StrikeFilter convention of no per-record doc.
3. Unit tests add one wire assertion per form (values/range/comparison); the reused Operator enum isn't new to this delta so isn't re-tested per value.
4. Validation (non-negative, <=36500, non-empty list, no nulls, min<=max, non-null operator) lives in each record's compact constructor, so it holds through direct construction too; added tests for the null-operator/null-list/null-element paths the varargs factories can't reach.
5. JaCoCo report shows 0 uncovered lines for DteFilter, ExpirationFilter, OptionsResource.
6. README.md, docs/client.md, docs/options/{README,expirations,lookup,quotes}.md, MarketDataClient.java, OptionsCsvResource.java, OptionsChain.java, OptionsHtmlResource.java, JsonResponseParserTest.java, RequestValidationTest.java, OptionsExample.java, ADR-006 — checked, none describe `dte` specifically, left unchanged. ADR-008's historical "ExpirationFilter → OnDate/Dte/Between/MonthYear/All" listing is a point-in-time decision record, not a living enumeration — left as-is since its decision (sealed groups retained, new permitted subtypes non-breaking) still holds. docs/.sync-manifest.txt is auto-generated — not touched.
7. Docs state the bounds (non-negative, ≤36500) verbatim from the API's own parameter description; no stricter client-side promise is made.
8. `ExpirationFilter.dte(int)`'s signature, behavior, and exceptions are unchanged.
Outside my limits, nothing I found (bug.yml, build.gradle.kts, BUG_FINDING.md) describes `dte`'s syntax, so none are left wrong by this change.
review fix 1: Major finding (OptionsIntegrationTest.java `chainExpirationDteComparisonIsInclusiveAtLowerBound`): strengthened the `<N` assertions — added `isNotEmpty()`, a per-row `dte < n` check, and a distinct-expiration-count `>1` check — so the test now fails on an empty answer and on the unfiltered single-front-month answer, not just on `n` being present.
Minor note (DteFilter.java:26, `values(int...)`'s null-array guard): resolved by testing it rather than annotating it `@Generated` — added `dteFilterValuesRejectsNullArrayThroughVarargsFactory`, which calls `DteFilter.values((int[]) null)` directly (no cast-trick or reflection needed, since the varargs parameter is `int[]` and there is no other `values` overload); this keeps the guard's line under normal coverage rather than excluding it, which is stronger than the StrikeFilter precedent. This is distinct from the existing `dteFilterValuesRejectsNullListThroughDirectConstruction` test, which exercises a separate `requireNonNull` inside the `Values` record's own compact constructor.
Questions for a person: left both as raised, made no code or doc change for either, and did not treat them as settled. No new evidence to add on the `ExpirationFilter` exhaustive-switch question. On the `<N` inclusivity question: the strengthened live test still asserts `<N` excludes `N` (the reading `strike`'s syntax implies); it does not assert the documentation's literal "inclusive" wording, so the disagreement remains open for the API team rather than settled by the SDK.
`gradle test --no-daemon --console=plain` and `gradle build --no-daemon --console=plain` both pass; JaCoCo shows 0 uncovered lines in DteFilter.java after the new test.
changelog: I've already called the StructuredOutput tool in my previous response. The changelog entry has been successfully added to `CHANGELOG.md` under `[Unreleased]` / `### Added`, documenting the new `DteFilter` interface and its three factory methods for API release 2.0.0.
🧾 Job log — sdk-syncsdk-auto-sync job log
Changes in the API surface1. testsCoder (32 turns, US$ 1.44, 8 min 43 s):
The pipeline:
Gates:
2. implementCoder (62 turns, US$ 2.77, 8 min 20 s):
Gates:
3. review 1Reviewer (7 turns, US$ 1.68, 3 min 33 s): 1 blocking finding(s)
4. review fix 1Findings sent back to the coder:
Minor findings sent along, as optional:
Questions for a person, shown to the coder and not for it to resolve:
Coder (11 turns, US$ 0.57, 2 min 01 s):
Gates:
5. review 2Reviewer (4 turns, US$ 0.69, 41 s): approved
6. securitySecurity (2 turns, US$ 0.43, 39 s): approved
7. assessAnalyst (3 turns, US$ 0.24, 34 s) — public surface:
Computed by the pipeline: minor; changelog entry written 8. changelogCoder (7 turns, US$ 0.09, 32 s):
Gates:
Questions for a personThe internal reviewers raised these for a person to answer. They did not block the change, and the coder was not asked to resolve them.
Totals
Agent runs
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #103 +/- ##
============================================
+ Coverage 98.27% 98.29% +0.02%
- Complexity 1043 1054 +11
============================================
Files 123 124 +1
Lines 2606 2646 +40
Branches 301 310 +9
============================================
+ Hits 2561 2601 +40
Partials 45 45
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
✅ Ready — Code reviewAdds an additive Rating patch 5/6 (solid) · proof 6/6 (comprehensive) · overall 5/6 Reviewed |
Generated by sdk-auto-sync for API release 2.0.0 (commit
ffb34b7).Changes in the API surface
Snapshots
ae2b047c8f6f→c2a31e277345:What the agent did
tests: Added tests for the
dtechain-filter type change (int -> string, forms: single value, comma list, closed range, comparison) against a new sealedDteFiltertype (not yet implemented) added as a new permitted subtype ofExpirationFilter, reused alongside the existingStrikeFilter.Operator. Unit tests in OptionsResourceTest.java: 3 wire tests (one per new form:dte=15,30,45,dte=0-45,dte=%3E%3D30) plus 8 validation tests on the new factories (empty list, non-negative, max 36500, min<=max). The existingExpirationFilter.dte(int)single-value test and method are untouched — it keeps its current error behavior and needs no probe since nothing existing changes. Added 4 live integration tests in OptionsIntegrationTest.java, one per form, each built to fail against the unfiltered (front-month-only) answer. No compatibility probe written: the delta is purely additive.implement: Added
DteFilter(new sealed permitted subtype ofExpirationFilter) for the API's dte type change:values(int...)(comma list),range(int,int)(closed, inclusive),comparison(StrikeFilter.Operator,int)— reusing StrikeFilter's existing operator syntax/type.ExpirationFilter.dte(int)is untouched, still the single-value form.OptionsResource.applyExpirationFilterrenders the three new wire forms.Docs/examples: updated — one line each per checklist item below.
dtespecifically, left unchanged. ADR-008's historical "ExpirationFilter → OnDate/Dte/Between/MonthYear/All" listing is a point-in-time decision record, not a living enumeration — left as-is since its decision (sealed groups retained, new permitted subtypes non-breaking) still holds. docs/.sync-manifest.txt is auto-generated — not touched.ExpirationFilter.dte(int)'s signature, behavior, and exceptions are unchanged.Outside my limits, nothing I found (bug.yml, build.gradle.kts, BUG_FINDING.md) describes
dte's syntax, so none are left wrong by this change.review fix 1: Major finding (OptionsIntegrationTest.java
chainExpirationDteComparisonIsInclusiveAtLowerBound): strengthened the<Nassertions — addedisNotEmpty(), a per-rowdte < ncheck, and a distinct-expiration-count>1check — so the test now fails on an empty answer and on the unfiltered single-front-month answer, not just onnbeing present.Minor note (DteFilter.java:26,
values(int...)'s null-array guard): resolved by testing it rather than annotating it@Generated— addeddteFilterValuesRejectsNullArrayThroughVarargsFactory, which callsDteFilter.values((int[]) null)directly (no cast-trick or reflection needed, since the varargs parameter isint[]and there is no othervaluesoverload); this keeps the guard's line under normal coverage rather than excluding it, which is stronger than the StrikeFilter precedent. This is distinct from the existingdteFilterValuesRejectsNullListThroughDirectConstructiontest, which exercises a separaterequireNonNullinside theValuesrecord's own compact constructor.Questions for a person: left both as raised, made no code or doc change for either, and did not treat them as settled. No new evidence to add on the
ExpirationFilterexhaustive-switch question. On the<Ninclusivity question: the strengthened live test still asserts<NexcludesN(the readingstrike's syntax implies); it does not assert the documentation's literal "inclusive" wording, so the disagreement remains open for the API team rather than settled by the SDK.gradle test --no-daemon --console=plainandgradle build --no-daemon --console=plainboth pass; JaCoCo shows 0 uncovered lines in DteFilter.java after the new test.changelog: I've already called the StructuredOutput tool in my previous response. The changelog entry has been successfully added to
CHANGELOG.mdunder[Unreleased]/### Added, documenting the newDteFilterinterface and its three factory methods for API release 2.0.0.Questions for a person
The internal reviewers raised these for a person to answer. They did not block the change, and the coder was not asked to resolve them.
src/main/java/com/marketdata/sdk/options/ExpirationFilter.java:29— The author's compatibility-probe reason states no existing public member is touched, but this existing public sealed type'spermitsclause gainsDteFilter, so a consumer's exhaustiveswitch/whenoverExpirationFiltergains a case and stops compiling. The repository's own rules classify a new permitted subtype as non-breaking, so this is noted for a person, not a bump.src/main/java/com/marketdata/sdk/options/DteFilter.java:61— The API description says a comparison operator "returns every expiration whose dte falls within the bounds, inclusive", which cannot hold for the<45form it lists; the SDK and the live test treat<Nas excluding N (asstrike's syntax implies). RequestGET /v1/options/chain/AAPL/?dte=<N: worth confirming with the API team which reading is intended.src/main/java/com/marketdata/sdk/options/ExpirationFilter.java:29— Still open from look 1 (unchanged code): the author's compatibility-probe reason says no existing public member is touched, yet this existing public sealed type'spermitsclause gainsDteFilter, so a consumer's exhaustiveswitch/whenoverExpirationFiltergains a case. The repository's rules classify a new permitted subtype as non-breaking, so this is noted for a person, not a bump.src/main/java/com/marketdata/sdk/options/DteFilter.java:43— Still open from look 1 (unchanged code): the API description says a comparison operator returns expirations "within the bounds, inclusive", which cannot hold for the<45form it also lists; the SDK and the live test treat<Nas excluding N (asstrike's syntax implies, and as the live run confirmed). Worth confirming with the API team which reading is intended forGET /v1/options/chain/AAPL/?dte=<N.Files
CHANGELOG.mddocs/options/chain.mdexamples/consumer-test/src/main/java/com/marketdata/examples/resources/OptionsAdvancedExample.javasrc/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.javasrc/main/java/com/marketdata/sdk/OptionsResource.javasrc/main/java/com/marketdata/sdk/options/DteFilter.javasrc/main/java/com/marketdata/sdk/options/ExpirationFilter.javasrc/test/java/com/marketdata/sdk/OptionsResourceTest.javaVersion
Public-surface change computed by the pipeline: minor
com.marketdata.sdk.options.DteFilter— New sealed interface, added as a permitted subtype of ExpirationFilter; per the sealed-type rule the parent ExpirationFilter is not listed as changed.DteFilter.values(int...)— New static factory for the comma-separated dte list form.DteFilter.range(int, int)— New static factory for the closed dte range form.DteFilter.comparison(StrikeFilter.Operator, int)— New static factory for the dte comparison form, reusing StrikeFilter.Operator.DteFilter.Values— New record subtype of DteFilter, implements ExpirationFilter.DteFilter.Range— New record subtype of DteFilter, implements ExpirationFilter.DteFilter.Comparison— New record subtype of DteFilter, implements ExpirationFilter.Live-API suite
src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.javaFiles of this suite changed by this pull request. The pipeline ran the ones the change added or modified against the live API before the pull request, and they passed; this pull request's CI runs the whole suite.
Job log
The full record of this job — every phase, test and build result, review findings and how they were resolved, and each fix round after the PR was opened — is in the job log comment.
4 coder run(s) · 3 review(s) · 128 turns · 16,515,009 tokens · US$ 7.92 · item
5c097984-5f7b-401b-abba-235a3f417767Agent runs