Skip to content

fix(kiota): document patches, Accept normalisation, expansion-gated read — the three live-run #3 failures - #109

Merged
ShocOne merged 1 commit into
mainfrom
fix/kiota-live-run-3
Aug 5, 2026
Merged

fix(kiota): document patches, Accept normalisation, expansion-gated read — the three live-run #3 failures#109
ShocOne merged 1 commit into
mainfrom
fix/kiota-live-run-3

Conversation

@ShocOne

@ShocOne ShocOne commented Aug 5, 2026

Copy link
Copy Markdown
Member

Why

go | Acceptance tests (kiota) run #3 failed on 4 of 10 packages (credential resource + ephemeral, alert_suppression_window, endpoint_label; everything else passed live). All three root causes are places the published document was allowed to overrule observed reality. Each fix moves authority back to the evidence.

1. Document patches (new sdk generate capability)

repeat.type = "none" failed with "not a member of models.Alerts_API_RepeatType". The recordings prove the API accepts and echoes "type": "none"; the published enum omits it; a closed Kiota enum therefore made the value unrepresentable in both directions — refused on write, and (proven offline) silently dropped on read.

Per the decision to fix this systemically: sdk generate now applies document patches — curated RFC 6902 corrections under openapi/<provider>/patches/*.patch.json, each with a mandatory justification naming its evidence — to a copy of the snapshot (whose bytes and checksum never change) before kiota reads it. Key properties:

  • Order-preserving: application walks the YAML node tree, not a decoded map. My first cut re-encoded through JSON, which sorted the schema keys — and immediately re-awoke kiota's unstable naming of colliding anonymous schemas. Document order is load-bearing; the patched copy differs from the snapshot by exactly the patched nodes.
  • Provable: -check applies the same patches, so drift checking still holds the committed tree to the pinned inputs. The lock's descriptionLocation is rewritten (one field, byte-targeted) back to the snapshot; only descriptionHash changes, deterministically.
  • Self-expiring: an add that finds its value already present refuses as stale — the prompt to delete the patch when the vendor fixes the document.
  • With no patches directory, the snapshot is read directly — zero behavior change for other providers.

Documented in docs/cli.md (drift-tested) and the glossary (named document patch — this repo reserves "spec" for the provider spec).

Two patches ship:

  • Alerts_API_RepeatType gains "none" (recording-justified). The suppression-window blueprint needed no change — the existing enum converters simply start working.
  • Endpoint_Agents_API_AgentTransfer's single-member anonymous allOf is collapsed into the plain object it definitionally is. This was the true root cause of the agents.go/proxies.go naming flip — the path excludes added in feat(kiota): parity foundations — every block kind fluent, full-spec SDK, single-nested rendering #107 only appeared to cure it (~1-in-5 failure surfaced again during this work). With the member named by its component, five consecutive sdk generate -check runs pass.

2. Accept normalisation (credential 406)

The credentials DELETE declares only error media types, so kiota emits Accept: application/problem+json alone — and ThousandEyes answers that with a bare 406 before considering the request. A small middleware in the hand-owned pilot client widens such degenerate Accept headers to admit the API's real success forms; a wire test pins it beside the gzip regression test from #106.

3. Expansion-gated read (endpoint_label filters null after apply)

The blueprint's own probe note has always said filters are "only returned when the read asks for expand=filters" — resty's read passes WithQueryParam("expand","filters"), but the port flattened every fluent trailing argument to nil, so readAfterWrite returned a label without filters and state contradicted the plan. The read chain's trailing argument is now a real request configuration (QueryParameters.Expand = [filters]) — pure blueprint data through the existing chain-argument import machinery; no emitter change needed.

Verification

  • 174/174 bindings check; probe verify 7/7 resources; provider drift 0 on both pilots; root + kiota pilot suites 0 failures; docs drift test green.
  • SDK drift check green five consecutive times with both patches applied.
  • Offline wire repros for all three fixes (filters round-trip, "none" deserialization, DELETE Accept header).

After merge: dispatch go | Acceptance tests (kiota) for live confirmation, then the tests wave (PR 3 of the parity plan) proceeds.

🤖 Generated with Claude Code

…ion, expansion-gated read

The three live acceptance failures each exposed a place the generated
document was allowed to overrule observed reality, and each fix moves the
authority back to the evidence.

sdk generate gains document patches: curated RFC 6902 corrections under
openapi/<provider>/patches/, each carrying a justification naming its
evidence, applied to a copy of the snapshot -- whose bytes and checksum
never change -- before kiota reads it. Application walks the YAML node
tree rather than a decoded map because document order is load-bearing:
kiota names colliding anonymous schemas by encounter order, and an
early JSON re-encode that sorted the keys re-awoke exactly the
nondeterminism this work went on to fix. A patched generation rewrites
only the lock's descriptionLocation, pointing it back at the pinned
snapshot; -check applies the same patches, so the committed tree stays
provable. An add that finds its value already present refuses as stale,
which is how a patch announces the vendor has fixed the document.

Two patches ship. The first adds "none" to Alerts_API_RepeatType: the
recordings show the API accepting and echoing it, the published enum
omits it, and a closed kiota enumeration made the value unrepresentable
-- refused on write, silently dropped on read. The second collapses
Endpoint_Agents_API_AgentTransfer's single-member anonymous allOf, the
true root of the agents.go/proxies.go naming flip the excludes only
appeared to cure; with the member named by its component, five
consecutive drift checks pass where roughly one in five used to fail.

The pilot client gains an Accept-normalising middleware: an operation
whose specification declares only error media types gets
Accept: application/problem+json alone from kiota, and the ThousandEyes
API answers that header with 406 before reading the request -- the
credential delete, live. The header is widened to admit the API's real
success forms, and a wire test pins it beside the gzip one.

endpoint_label's read chain now passes a request configuration asking for
expand=filters, which the blueprint's own probe note has always said the
read must do; the port had flattened every trailing argument to nil, so
each read-after-write returned a label without filters and the state
promptly contradicted the plan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ShocOne
ShocOne merged commit de4a75e into main Aug 5, 2026
15 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant