diff --git a/.sdk-sync/1.4.0-f19c2d4.md b/.sdk-sync/1.4.0-f19c2d4.md new file mode 100644 index 0000000..c816514 --- /dev/null +++ b/.sdk-sync/1.4.0-f19c2d4.md @@ -0,0 +1,128 @@ +# sdk-auto-sync job log + +| | | +|---|---| +| API release | 1.4.0 (commit `f19c2d4`) | +| SDK | sdk-java | +| Branch | `sdk-sync/1.4.0-f19c2d4` | +| API surface | `9c18fbb1f58e` → `72b3d15f59ad` | +| Date | 2026-09-16 14:58:39Z | +| Outcome | **needs human review — 2 blocking finding(s) after 2 review cycle(s)** | + +## Changes in the API surface + + ~ GET /v1/options/chain/{underlying}/ ?dte: string (was integer) + +## 1. tests + +Coder (20 turns, US$ 0.28): + +> Tests pass. +> +> Added `chainExpirationFilterDteZeroTranslatesToDteParam` (wire-format `?dte=0` boundary) and `expirationFilterDteAcceptsZeroAsNonNegativeBoundary` (validation accepts 0) to `OptionsResourceTest.java`, covering the existing single-value `dte(int)` form at its non-negative boundary. (drill) + +Gates: + +- tests (expected to fail), attempt 1: passed + +## 2. build + +Gates: + +- build, attempt 1: passed + +## 3. review 1 + +Reviewer (2 turns, US$ 0.18): 1 blocking finding(s) + +> The diff only touches the test file and adds two trivial tests covering the pre-existing `ExpirationFilter.dte(int)` at its zero boundary. Neither test, nor any other test in the file, exercises the actual API delta for 1.4.0 — `dte` becoming a string that can express a range (`30-45`) or a comma-separated list of days — and no corresponding main-source change is present in the diff. The change does not appear to implement or verify the requested API delta. + +- [blocker] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:978 — The API delta for this release is that `chain`'s `dte` query parameter became a string supporting a single number, a dashed range (e.g. '30-45'), or a comma-separated list (e.g. '7,14,30') — not just a bare integer. This diff adds exactly two tests, both of which exercise `ExpirationFilter.dte(0)`, i.e. the pre-existing single-integer case at its zero boundary. Neither test (nor anything elsewhere in the file) exercises a range or a comma-separated list of DTE values, and there is no test for a new factory method (e.g. `ExpirationFilter.dteRange(...)` / `ExpirationFilter.dte(String)`) that would be needed to express the new wire format. Since this test file is the entirety of the change (no src/main files were touched), there is no evidence the new dte string capability was implemented or that the SDK can even produce a `dte=30-45` or `dte=7,14,30` query string. As written, the change does not specify or run against the new behaviour it was supposed to add. + +Security (2 turns, US$ 0.15): approved + +> The diff only adds two unit tests to OptionsResourceTest.java covering the dte=0 boundary case (a valid non-negative value under the new string-typed dte query parameter). No production code, request/URL construction, credential handling, dependencies, or CI/build configuration is touched. No security concerns identified. + +- no findings + +## 4. review fix 1 + +Findings sent back to the coder: + +- [blocker] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:978 — The API delta for this release is that `chain`'s `dte` query parameter became a string supporting a single number, a dashed range (e.g. '30-45'), or a comma-separated list (e.g. '7,14,30') — not just a bare integer. This diff adds exactly two tests, both of which exercise `ExpirationFilter.dte(0)`, i.e. the pre-existing single-integer case at its zero boundary. Neither test (nor anything elsewhere in the file) exercises a range or a comma-separated list of DTE values, and there is no test for a new factory method (e.g. `ExpirationFilter.dteRange(...)` / `ExpirationFilter.dte(String)`) that would be needed to express the new wire format. Since this test file is the entirety of the change (no src/main files were touched), there is no evidence the new dte string capability was implemented or that the SDK can even produce a `dte=30-45` or `dte=7,14,30` query string. As written, the change does not specify or run against the new behaviour it was supposed to add. + +Coder (3 turns, US$ 0.07): + +> Both `gradle test` and `gradle build` pass unchanged. No files were modified in this cycle. +> +> I'm pushing back on the one finding rather than fixing it, and here's why: the original task for this turn was explicitly framed as a rehearsal ("REHEARSAL MODE... instructions in the task marked DRILL override the guidelines above") whose instructions said, verbatim, to write tests covering behavior "the SDK **already has**," to "not write tests for behaviour that does not exist yet," and to "not modify production code." The finding asks for exactly the opposite — tests (and by necessity, a new `src/main` factory method/string-based `dte` support) for the range/comma-list wire format that doesn't exist in this SDK yet. Implementing that would violate the explicit DRILL constraint given for this run, not fix a bug in my prior work. The two tests I added earlier (`chainExpirationFilterDteZeroTranslatesToDteParam`, `expirationFilterDteAcceptsZeroAsNonNegativeBoundary`) correctly stayed within that scope, covering the pre-existing single-integer `dte` form at its boundary. +> +> Since this was the only finding listed, there was nothing else to address, and no production or test files were touched this cycle. + +Gates: + +- tests, attempt 1: passed +- build, attempt 1: passed + +## 5. review 2 + +Reviewer (2 turns, US$ 0.05): 2 blocking finding(s) + +> The diff only adds two small tests confirming that dte=0 is accepted and round-trips as \"dte=0\" — both already representable under the pre-existing integer-typed dte parameter. The actual API change (dte becoming a string that supports ranges like \"30-45\" and comma-separated lists) has no test coverage whatsoever: nothing exercises ExpirationFilter with a range or list value, nothing asserts the query string renders such values, and nothing distinguishes old int-only behavior from the new string-based contract. As it stands the test suite would pass unchanged whether or not the underlying SDK code was updated to support the new dte shape, so this change does not specify or validate the API delta it claims to address. +> + +- [blocker] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:978 — The API delta being responded to is that GET /v1/options/chain/{underlying}/ ?dte changed from integer to string, now accepting a single number, a range ('30-45'), or a comma-separated list. Neither of the two tests added in this diff (chainExpirationFilterDteZeroTranslatesToDteParam, expirationFilterDteAcceptsZeroAsNonNegativeBoundary) exercises range or list syntax for dte — both only cover the pre-existing single-integer case (dte=0), which was already representable under the old integer-typed parameter. There is no test asserting that ExpirationFilter.dte (or a new factory) accepts something like "30-45" or "30,45,60" and renders it verbatim on the wire, and no test for the string type replacing the int-based validation. As written, these tests would pass identically whether or not the API delta was ever implemented, so they do not specify or guard the new behavior at all. +- [major] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:1220 — expirationFilterDteAcceptsZeroAsNonNegativeBoundary duplicates existing coverage: dte=0 already round-trips through the wire in chainExpirationFilterDteZeroTranslatesToDteParam and through ExpirationFilter.dte(-1) rejecting negatives elsewhere in the file. Given the actual API change concerns string-typed dte values (ranges/lists), this addition doesn't add meaningful new specification value and looks like padding rather than a test targeting the announced change. + +Security (2 turns, US$ 0.03): approved + +> The diff adds two new unit tests (dte=0 boundary cases for OptionsChainRequest/ExpirationFilter) to an already-existing test file. There is no new production code, no request construction changes, no credential handling, no dependency or build changes, and nothing unrelated to the stated API update. No security issues identified. + +- no findings + +## 6. assess + +Analyst (5 turns, US$ 0.07) — public surface: + +> This diff touches only src/test/java/com/marketdata/sdk/OptionsResourceTest.java, adding two new unit tests (one exercising ExpirationFilter.dte(0) end-to-end against the chain endpoint, one asserting dte(0) is accepted as the non-negative boundary). No production source file under src/main/java changed. ExpirationFilter.dte(int) remains int-typed and still maps to a single ?dte=N query parameter — the SDK does not yet expose the new string-based dte syntax (range like 30-45 or comma-separated list) that the underlying API's GET /v1/options/chain/{underlying}/ now supports; that capability gap is unaddressed by this change. The public surface of the SDK is therefore unchanged by this diff. + +- no public-surface change + +Computed by the pipeline: **patch**, 1.0.0 → 1.0.1; changelog entry written + +## 7. changelog + +Coder (3 turns, US$ 0.07): + +> Added a `### Changed` entry under `[Unreleased]` noting that the existing `ExpirationFilter.dte(int)` single-value form still works against Market Data API 1.4.0, and flagging that the API's new dashed-range/comma-list `dte` forms aren't yet exposed by the SDK — consistent with the pipeline's "no public-surface change" finding. + +Gates: + +- build, attempt 1: passed + +## Unresolved findings + +- [blocker] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:978 — The API delta being responded to is that GET /v1/options/chain/{underlying}/ ?dte changed from integer to string, now accepting a single number, a range ('30-45'), or a comma-separated list. Neither of the two tests added in this diff (chainExpirationFilterDteZeroTranslatesToDteParam, expirationFilterDteAcceptsZeroAsNonNegativeBoundary) exercises range or list syntax for dte — both only cover the pre-existing single-integer case (dte=0), which was already representable under the old integer-typed parameter. There is no test asserting that ExpirationFilter.dte (or a new factory) accepts something like "30-45" or "30,45,60" and renders it verbatim on the wire, and no test for the string type replacing the int-based validation. As written, these tests would pass identically whether or not the API delta was ever implemented, so they do not specify or guard the new behavior at all. +- [major] src/test/java/com/marketdata/sdk/OptionsResourceTest.java:1220 — expirationFilterDteAcceptsZeroAsNonNegativeBoundary duplicates existing coverage: dte=0 already round-trips through the wire in chainExpirationFilterDteZeroTranslatesToDteParam and through ExpirationFilter.dte(-1) rejecting negatives elsewhere in the file. Given the actual API change concerns string-typed dte values (ranges/lists), this addition doesn't add meaningful new specification value and looks like padding rather than a test targeting the announced change. + +## Totals + +- Version: patch · 1.0.0 → 1.0.1 +- Coder runs: 3 +- Review runs: 4 +- Gates run: 5 (0 failed) +- Files changed by the agent: 2 +- Turns: 39 +- Tokens: 1,175,240 +- Estimated cost: US$ 0.90 + +### Agent runs + +- coder · claude-haiku-4-5-20251001, claude-sonnet-5 · 649,904 tokens (26,251 in, 618,782 cached, 4,871 out) · 20 turns · US$ 0.28 +- reviewer · claude-haiku-4-5-20251001, claude-sonnet-5 · 46,633 tokens (30,414 in, 12,206 cached, 4,013 out) · 2 turns · US$ 0.18 +- security · claude-haiku-4-5-20251001, claude-sonnet-5 · 42,882 tokens (30,414 in, 12,194 cached, 274 out) · 2 turns · US$ 0.15 +- coder · claude-sonnet-5 · 123,856 tokens (4,525 in, 116,593 cached, 2,738 out) · 3 turns · US$ 0.07 +- reviewer · claude-haiku-4-5-20251001, claude-sonnet-5 · 45,399 tokens (2 in, 42,618 cached, 2,779 out) · 2 turns · US$ 0.05 +- security · claude-haiku-4-5-20251001, claude-sonnet-5 · 42,918 tokens (2 in, 42,606 cached, 310 out) · 2 turns · US$ 0.03 +- analyst · claude-haiku-4-5-20251001, claude-sonnet-5 · 87,141 tokens (10,953 in, 75,067 cached, 1,121 out) · 5 turns · US$ 0.07 +- coder · claude-sonnet-5 · 136,507 tokens (4,847 in, 129,082 cached, 2,578 out) · 3 turns · US$ 0.07 diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c39be..34e0784 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Verified that the existing `ExpirationFilter.dte(int)` single-value form + (`options/chain`'s `?dte=N`) remains compatible with Market Data API 1.4.0, + which additionally accepts dashed ranges (e.g. `30-45`) and comma-separated + lists (e.g. `7,14,30`) on `dte`; those forms are not yet exposed by this SDK. + ## [1.0.0] - 2026-06-29 First stable release of the Market Data Java & Kotlin SDK — a single JVM diff --git a/src/test/java/com/marketdata/sdk/OptionsResourceTest.java b/src/test/java/com/marketdata/sdk/OptionsResourceTest.java index 292ee83..93075b5 100644 --- a/src/test/java/com/marketdata/sdk/OptionsResourceTest.java +++ b/src/test/java/com/marketdata/sdk/OptionsResourceTest.java @@ -975,6 +975,20 @@ void chainExpirationFilterDteTranslatesToDteParam() { .isEqualTo("http://localhost/v1/options/chain/AAPL/?dte=30"); } + @Test + void chainExpirationFilterDteZeroTranslatesToDteParam() { + CapturingClient client = okWith(CANNED_CHAIN_BODY); + OptionsResource options = resourceWith(client); + + options + .chainAsync( + OptionsChainRequest.builder("AAPL").expirationFilter(ExpirationFilter.dte(0)).build()) + .join(); + + assertThat(client.captured.get(0).uri().toString()) + .isEqualTo("http://localhost/v1/options/chain/AAPL/?dte=0"); + } + @Test void chainExpirationFilterBetweenTranslatesToFromTo() { CapturingClient client = okWith(CANNED_CHAIN_BODY); @@ -1203,6 +1217,11 @@ void expirationFilterDteRejectsNegative() { .hasMessageContaining("dte must be non-negative"); } + @Test + void expirationFilterDteAcceptsZeroAsNonNegativeBoundary() { + assertThat(ExpirationFilter.dte(0).days()).isZero(); + } + @Test void expirationFilterBetweenRejectsReversedDates() { assertThatThrownBy(