Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Each cell shows whether the section is implemented and how it is attested for th
| Repo naming (`{service}-export-cli`) | human | human | human |
| Timezone policy | human | human | human |
| Date flags (`--since` / `--until`) — surface | **machine** | **machine** | **machine** |
| Date flags — local-midnight semantics | human | human | human |
| Date flags — local-midnight semantics | **machine** | **machine** | **machine** |
| `--format` flag surface (documented, rejects unknown) | human | human | **machine** |
| `--format markdown` (default) | human | human | **machine** |
| `--format json` | human | human | **machine** |
Expand Down
19 changes: 8 additions & 11 deletions compat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,12 @@ formats.RunContract(t, compat.Runner{

`SkipDataPath` and `SupportedFormats` compose: `nil` SupportedFormats + `SkipDataPath: true` is the typical liftoff/crono shape today (declare the full surface, but skip the data-path subtests until creds are available). Use `SupportedFormats: []string{...}` instead of `SkipDataPath: true` when the CLI structurally lacks a codec — those are two different gaps and should not be confused.

## What it does NOT cover yet
## Local date-window coverage

The actual local-midnight semantics of `--since 2026-04-15` remains **human-attested** until exporters adopt the resolved-window check in CI. Black-box coverage can use either:

- a `--print-resolved-window`-style affordance on every CLI (a substantive contract change, intentionally out of scope of the first compat-test cut), or
- per-upstream recorded HTTP fixtures (heavy, and pinned to specific API shapes).

The opt-in `dates.RunResolvedWindow` check below supports the first approach.
The `dates.RunResolvedWindow` check covers explicit date bounds in multiple
local timezones, including both daylight-saving transitions. Crono, Liftoff,
and Withings invoke it in their own compatibility CI. It verifies the reported
window; request and filtering behavior requires exporter-specific tests.

## Adding a new contract test

Expand All @@ -176,11 +174,10 @@ The stub has two modes (`STUBCLI_MODE=flat` and `STUBCLI_MODE=cobra`). The flat-

The stub additionally honors `STUBCLI_FORMATS` (comma-separated) to restrict which codecs it will accept at parse time — used by the formats bundle's `TestRunContract_PartialCodec_SkipsCSV` self-test. Setting `STUBCLI_FORMATS=markdown,json` makes the stub reject `--format csv`, so the partial-codec self-test proves the `SupportedFormats` skip is actually load-bearing: without it, the test would fail at `CSVHasHeader` because the stub rejects csv.

## Proposed resolved-window diagnostic
## Resolved-window diagnostic

Exporters adopting the proposed `--print-resolved-window` flag can call
`dates.RunResolvedWindow(t, runner)` separately from `RunContract` while
rollout is in progress. The command prints exactly one line:
Exporters call `dates.RunResolvedWindow(t, runner)` separately from
`RunContract` to check the `--print-resolved-window` flag. The command prints exactly one line:
`since=VALUE until_exclusive=VALUE`, followed by a newline. Finite bounds are
RFC3339 timestamps in local time; absent bounds are `unbounded`. The upper bound is the next local calendar midnight for an
explicit inclusive `--until`. It exits successfully without credentials or
Expand Down
15 changes: 5 additions & 10 deletions compat/dates/dates.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,9 @@
// - A flag-validation failure does not perform a network request.
// - `--help` exits zero and does not perform a network request.
//
// What is intentionally NOT machine-attested yet:
//
// - The actual local-midnight semantics of `--since 2026-04-15` (i.e.
// "the window starts at local midnight, not UTC midnight"). Asserting
// this black-box requires either a `--print-resolved-window` (or
// equivalent) affordance on every CLI, or a recorded HTTP fixture per
// upstream. Both are out of scope for the first compat-test cut and
// tracked separately in quantcli/common.
// RunResolvedWindow additionally checks explicit local date bounds and the
// exclusive end of the selected day in multiple timezones, including DST
// transitions. Exporters invoke it separately from RunContract.
//
// Exporter usage:
//
Expand Down Expand Up @@ -217,8 +212,8 @@ func noNetworkEnv() []string {
}
}

// RunResolvedWindow checks the optional offline window diagnostic on each
// declared command. Call it separately while exporters adopt the proposal.
// RunResolvedWindow checks the offline window diagnostic on each declared
// command. Exporters call it separately from RunContract.
func RunResolvedWindow(t *testing.T, r compat.Runner) {
t.Helper()
subs := r.Subcommands
Expand Down
Loading