Skip to content
skyl

Roadmap

What stands between skyl and a library a company can adopt.

A living document, ordered by what blocks adoption rather than by what is interesting to build. It came out of an audit that went looking for the gap between "CI is green" and "a company can depend on this" — and found the gap was elsewhere, and larger than the test suite could see.

Where this came from#

CI was green: four modules, -race, coverage above every floor, a clean linter, a fuzzer surviving millions of executions. Three things dominated everything else, and only one of them was visible from inside the test suite.

FindingStatus
skyl could not be installed — no tags, and submodules required the root at v0.0.0 behind replace directives Go ignoresFixed
The Go 1.26 floor was not justified by the code — nothing outside tests used anything newer than 1.22Fixed
Some documented rules were not met — §6.5 (honour ProviderOptions), §6.1 (never silently drop data), §8.3 (runnable examples)Fixed

Phase 0 — Defects ✅#

Nine bugs with specific failure modes, each fixed with a regression test that failed before the fix. The ones worth knowing about because they changed behaviour:

DefectFailure mode
Anthropic ignored ProviderOptionsThe only escape hatch to cache_control, top_k and beta features was unreachable there — with no workaround at all.
TotalTokens double-counted cache readsCost dashboards over-reported by up to ~2× on a well-cached agent loop.
Content arrays silently droppedvLLM and some Azure/OpenRouter upstreams yielded a successful response with empty text.
Retry-After clamped to maxDelayA standard Retry-After: 60 was truncated to 30s, so the retry landed inside the still-open window and was rejected again.
Transport errors lost their causeerrors.Is(err, context.DeadlineExceeded) was false after a timeout, and a permanent TLS misconfiguration was retried as transient.
Anthropic tool schemas rebuilt lossily$defs, $ref and oneOf were dropped, so the same skyl.Tool behaved differently across providers — undercutting the one feature the library is named for.
Gemini ignored Request.Thinking&Thinking{Enabled: false} could not disable reasoning, so a real cost control silently did nothing.
Truncated streams looked completeA connection dropped mid-generation returned a partial answer with a nil error.
Refusals reported as successErrRefusal was never produced by any adapter, and the gateway's 422 branch was unreachable.

Phase 1 — Prove correctness without credentials ✅#

The sandbox: a local server speaking all four wire protocols, with fault models for statuses, truncation and mid-stream errors. Plus runnable Example functions, benchmarks on the per-token paths, and internal/cassette for recorded replay.

The benchmark caught tool-argument accumulation being quadratic — 2.2 MB allocated to assemble a few kilobytes. The fix brought it to 34 KB, and the benchmark stays as the guard.

Phase 2 — Make it installable ✅#

Tags, the replace-directive removal, go.work for local development, and a CI check that refuses a tag whose modules still carry a replace or a v0.0.0 require. Either one publishes a module nobody can install, and the proxy will serve it forever.

Phase 3 — What an enterprise review asks for ✅#

Supply chain (govulncheck, CodeQL, Scorecard, Dependabot, SBOM, signed provenance, digest-pinned actions, DCO), governance (NOTICE, per-module licences, CODEOWNERS, MAINTAINERS.md, code of conduct, issue templates), and the gateway hardening: /readyz, /metrics, graceful drain, concurrency limits, rotatable labelled tokens, CORS, SSE keep-alives, and env vars for every skyl.Option.

Plus skyl/otel as a fourth module, and data-handling and threat-model documents.

Phase 4 — Documentation that survives an evaluation#

In progress. The feature matrix, the silently-ignored list, and this site.

The one thing that still blocks adoption#

This is the gap, stated plainly. It is closable by one contributor with a key — either by running the integration suite, or by recording a cassette, which improves the suite for everyone permanently.

Deferred, deliberately#

  • A generated model registry — context windows, pricing, modality — refreshed from live endpoints by CI. Generated, never hand-typed, so it cannot silently rot.
  • Cross-provider fallback. A product decision, not a library one. See Choosing a Provider.
  • An Agent interface. Possibly a v2. The Copilot agent runtime is a real, interesting capability — it just needs a different shape than Completer.

What this is not#

Not a promise of dates. It is an ordered list of what blocks adoption, and it changes when the answer to that question changes.

Edit this page on GitHub