reasoninglayer 1.0.3

Rust client SDK for the Reasoning Layer API
Documentation
# Changelog

All notable changes to this crate are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this crate adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.0.3] — 2026-05-04

## [1.0.2] — 2026-05-04

## [1.0.1] — 2026-05-04

## [1.0.0] — 2026-05-04

## [0.2.1] — 2026-04-27

### Documentation

- Removed all remaining mentions of the upstream TypeScript SDK from public-facing
  docstrings (crate-level docs, `ClientConfig`, `Error`/`ApiErrorKind`,
  `ReasoningLayerClient`, `WebSocketConnection`, `LubRequest`, `GoalPayload`,
  `OsfClauseDto` declaration-order rationale, `UICatalogEntry`, `OptimizeClient`,
  `bulk_create_sorts`/`bulk_create_terms` aliases) and from the `quickstart` example
  header. Also dropped the `snake_case` self-reference from the README intro and the
  crate-level docstring — that's the obvious idiomatic default in a Rust crate.

## [0.2.0] — 2026-04-27

### Wire-contract fixes (would have failed against a real backend in 0.1.x)

- `visualization::lattice_dot` returned `serde_json::Value` but the backend serves
  `text/plain` GraphViz DOT — every call would have failed with a JSON-parse error. Added a
  text-mode transport to `HttpClient` (`get_text` / internal `request_raw_bytes`) and
  changed the method to return `String`.
- `causal::ValidateDidRequest` had `outcome` and `controls` fields, but the backend expects
  `outcome_pre`, `outcome_post`, `covariates`. Renamed and added `ValidateDidResponse` (was
  returning untyped `Value`).
- Constraints surface: backend uses integer finite domains (`i64`), but SDK had `f64`
  throughout. Fixed `ArithmeticExprDto::Constant`, `ArithmeticConstraintDto::Domain`,
  every bindings map across `SolveConstraintRequest/Response`, `ConstraintSessionStatus`,
  `AddConstraintsRequest/Response`, `BindVariablesRequest/Response`, and
  `FdDomainStateDto::values/min/max`. Also `CreateConstraintSessionResponse::created_at`
  was `u64` but the backend serializes `chrono::DateTime<Utc>` as an ISO-8601 string —
  switched to `String`.
- `namespaces::add_import` / `add_export` returned `Result<Json>` for endpoints that
  respond with 200 OK and an empty body — switched to `Result<()>`.
- `cdl::forward_chain` and `cdl::forward_chain_tagged` were calling `/cdl/forward-chain`
  and `/cdl/forward-chain-tagged`; the actual backend paths are
  `/cdl/forward-chain/differentiable` and `/cdl/forward-chain/tagged`. Added the missing
  `dynamic_add_sort` endpoint. CDL feature pairs / scoring fields corrected from `f64` to
  `f32` to match backend.
- `ilp` training-example pairs and pattern bases corrected from `f64` to `i64`;
  `processing_time_ms` corrected from `u64` to `u128` across all responses.
- `terms::BulkAddTermsResponse::processing_time_ms` corrected from `u64` to `u128`.
- `sorts::SortOriginDto::{LlmExtracted,Learned,AutonomousLearning}::confidence` corrected
  from `f64` to `f32`.
- `reviews::SortSuggestionDto` rewritten to match backend
  (`{sort_name, confidence, reason: Option<String>}`); the previous SDK shape was a
  speculative 6-field struct that would have failed to deserialize any real response.
- `action_reviews::ActionReviewResponse::status` was `Option<ActionReviewStatusDto>` but
  the backend always emits the field — dropped the Option (and added `Default` on the
  enum).
- `control::CreateModuleRequest` was missing `parents: Vec<String>`; response was missing
  `success: bool`. `ResolveSymbolRequest` had an extra `current_module` field the backend
  never reads. `ImportModuleResponse` was missing `importer_module: String` and
  `success: bool`.
- `reasoning::EntailmentRequest` and `DisentailmentRequest` had `antecedent`/`consequent`/
  `facts` typed as `TermInputDto` from the homoiconic surface, but the backend's
  `/reasoning/entailment` and `/reasoning/disentailment` expect `OsfClauseDto` (a
  constraint-based representation in `dto::inference`). Authored a new
  `src/types/osf.rs` module with `OsfClauseDto`, `OsfConstraintDto`, `OsfFeatureValueDto`,
  `OsfFeatureTargetDto`. Also fixed `FuzzySubsumptionResponseReasoning` (was missing
  `computation_time_ms`) and added `FuzzyMergeResponseReasoning` for `/reasoning/merge`.

### Typed surface additions (formerly `serde_json::Value` end-to-end)

- **Visualization, causal, statistical, communities, fuzzy, constraints, namespaces,
  collections, reasoning** — every method now uses typed request/response DTOs.
- **Reviews, ActionReviews** — fully typed including the GET-with-query endpoints.
  Added `HttpClient::get_with_typed_query` (uses `serde_urlencoded`) so query DTOs
  serialize properly.
- **WebhookActions** — all 4 methods plus the previously-missing
  `list_pending_invocations` (GET `/invocations`).
- **Control** — all 17 methods (cond, call_once, implies, naf, forall, findall, cut,
  undo, the four backtrackable/global assignment ops, the five module-management
  endpoints).
- **Ilp, Cdl** — fully typed (CDL gained `dynamic_add_sort`).
- **Synthetic** — 9 methods typed, with extensive nested DTOs for round-trip
  verification.
- **Utilities** — all 21 methods (relational arithmetic, math, bitwise, modular, every
  string op, copy/batch/deep-copy).
- **Ingestion** — markdown + document/OCR endpoints typed
  (`IngestMarkdownRequest/Response`, `IngestDocumentRequest/Response` with
  `DocumentSource`/`DocumentType`/`DocumentParser`/`OcrConfigDto`); session-management
  and DLQ endpoints stay on `Json` because the backend itself uses `serde_json::Value`
  there.
- **Execution** — all 21 methods (Wild_Life trail-based proof search). Tagged enums for
  `ExecutionValueDto`, `TrailEntryDto`, `GoalDto` (recursive `IfThenElse`),
  `LazyEvalResponse`, `ApplyCurriedResponse`. Three residuation endpoints with
  still-evolving wire shapes remain on `Json`.
- **ProofEngine** — all 20 term-store / rule-store / eval methods. Tagged enums for
  `TermStoreValueDto`, `RuleConstraintDto`, `EvalBuiltinResponse`.
  `list_eval_functions` uses `get_with_typed_query` for the optional `?category=` filter.
- **Conversation** — 8 methods typed; recursive `ProofTraceNodeDto`, free-form
  `OsfqlValueDto`, and `UICustomizationDto` kept as `serde_json::Value` aliases.
- **Oversight** — all 6 HTTP methods (`judge`, `judge_refine`, `create_session`,
  `ingest_step`, `get_session`, `finalize`).
- **NeuroSymbolic** — all 10 methods typed on the response side. Request payloads stay
  on `Json` where the backend accepts free-form configuration.
- **Cognitive** — 10 core agent operations typed (`create_agent`, `add_goal`,
  `add_belief`, `run_cycle`, `get_state`, `reflect`, `adapt`, `run_integrated_cycle`,
  `get_extended_state`). Plans/HTN/messaging/episodes/feedback endpoints remain on
  `Json` because the backend itself uses `serde_json::Value` there.

### Documented as legacy

- `ResearchClient` — backend no longer mounts `/research/*` routes; every method
  currently 404s against a live server. Preserved for source compatibility with 0.1.x
  but slated for removal in a future minor release.

### Other changes

- README rewritten: dropped the early-stage "Status" section, the Quick start now uses
  the term CRUD surface, and the resource-surface table no longer references internal
  phase nomenclature.
- Authored new SDK type modules: `osf`, `cognitive`, `conversation`, `execution`,
  `ingestion`, `neuro_symbolic`, `oversight`, `proof_engine`, `synthetic`, `utilities`.

### Internal

- Audited every existing DTO module against the backend handlers/DTOs (Tier 1 + Tier 2).
  Drift catalogued and fixed in this release; integration tests previously locked in
  whatever the SDK happened to send (round-tripping mocks against itself), so the
  audits relied on direct backend comparison.
- `serde_urlencoded` added as a direct dependency for typed query-string serialization.

## [0.1.2] — 2026-04-27

## [0.1.1] — 2026-04-27

### Added

- `release.toml` configuration for [`cargo-release`](https://github.com/crate-ci/cargo-release). Run `cargo release patch --execute` (or `minor` / `major` / explicit `X.Y.Z`) to bump the version, refresh `Cargo.lock`, rewrite the `CHANGELOG.md` heading, run tests + `cargo publish --dry-run`, commit, tag `vX.Y.Z`, and push. The actual `cargo publish` to crates.io still runs from GitLab CI on tag push using the masked `CARGO_REGISTRY_TOKEN` variable — no local registry token required.

## [0.1.0] — 2026-04-24

### Rust version policy

This crate **tracks current stable Rust** and does not maintain a fixed MSRV. The dependency tree (notably `idna` → `icu_*` and the `tokio` / `reqwest` ecosystem) bumps minimum Rust versions in patch releases; pinning a fixed MSRV would either ship a claim we can't keep, or force us to lag dep upgrades and miss bug/security fixes. CI runs against `rust:slim` (the latest stable Rust image) on every push. If you need to consume this SDK from a non-current toolchain, open an issue with your specific constraint and we'll evaluate.

### Added

#### Phase 1 — core resources (fully typed DTOs)

- `ReasoningLayerClient` with [`ClientConfig`](src/config.rs) builder (`base_url` + `tenant_id` required; `user_id`, `namespace_id`, `authenticated_user`, `bearer_token`, `timeout`, `max_retries`, `retry_on_503` optional).
- 4 resource clients covering ~60 methods: `sorts` (28), `terms` (9), `inference` (20), `query` (8), plus friendly aliases `types`, `records`, `rules`.
- HTTP client over `reqwest` with auth header injection (`X-Tenant-Id`, `X-SDK-Version`, `X-SDK-Language: rust`, `X-User-Id`, `X-Namespace-Id`, `X-Authenticated-User`, `Authorization: Bearer`), exponential backoff with jitter on 429 / 503 / network errors (honours `Retry-After`), per-call `RequestOptions` overrides.
- Error hierarchy: `Error::{Api(Box<ApiError>), Timeout, Validation, Network, Serde, Url}` with `ApiErrorKind` (BadRequest, Authentication, Forbidden, NotFound, ConstraintViolation, RateLimit, InternalServer, Other) and structured accessors (`constraint_violation()`, `rate_limit()`).
- Two serialization formats wired correctly: tagged `ValueDto` for term CRUD/query, untagged `TermInputDto`/`FeatureInputValueDto` for inference (with newtype-wrapped struct variants using `deny_unknown_fields` for correct routing between `Variable` and `ConstrainedVariable`).
- Builders: `Value::{string/integer/real/boolean/uninstantiated/list/reference/fuzzy_scalar/fuzzy_number/set}`, `FuzzyShape::{triangular/trapezoidal/gaussian/cyclic_gaussian/sigmoid/bell/sigmoid_difference/gaussian_product/sigmoid_product/cosine/spike/cauchy/s_shape/z_shape/pi_shape/piecewise_linear}`, `psi()`, `psi_by_id()`, `var()`, `constrained()`, `term_ref()`, `guard()`. Plus `From<T>` impls for `ValueDto` and `FeatureInputValueDto` from `&str`, `String`, `i64`, `i32`, `f64`, `bool`, `Vec<T>`.

#### Phase 2 — remaining resources (wire-compatible, Value-typed where not Phase 3-upgraded)

- 45 additional resource clients accessible via `client.{resource}()`: `health`, `admin`, `osfql`, `context`, `rl_training`, `rag`, `generation`, `image_extraction`, `extract`, `preferences`, `discovery`, `functions`, `ontology`, `analysis`, `scenarios`, `spaces`, `row`, `sources`, `ui`, `optimize` (Phase 2a — typed DTOs) plus `fuzzy`, `causal`, `statistical`, `communities`, `visualization`, `constraints`, `namespaces`, `collections`, `reasoning`, `reviews`, `action_reviews`, `webhook_actions`, `control`, `ilp`, `cdl`, `synthetic`, `utilities`, `ingestion`, `execution`, `proof_engine`, `conversation`, `research`, `cognitive`/`agents`, `oversight`, `neuro_symbolic` (Phase 2b/c).
- Path resolver handles absolute prefixes (`/health`, `/ready`, `/live`, `/metrics`, `/ws/`, `/api-docs`, `/swagger-ui`) without `/api/v1` prefix.
- `PATCH` verb and `post_with_query` support for endpoints that need both body + query.
- WebSocket infrastructure (`reasoninglayer::ws`): `WebSocketConnection::connect(url)` with auto-reconnect (exponential backoff, 10 attempts, 30s cap), `next_message()`/`send()`/`close()`/`on_reconnect()`. URL builders via `client.cognitive().agent_events_url(agent_id)`, `cognitive_cycle_url(agent_id)`, `client.oversight().session_stream_url(session_id)`.
- SSE infrastructure (`reasoninglayer::sse`): `stream(&client, method, path, body, options)` returns `Stream<Item = Result<SseEvent, Error>>` with full auth headers.

#### Phase 3 — typed DTO upgrades

- `fuzzy`, `causal`, `statistical`, `communities`, `visualization`, `constraints`, `namespaces`, `collections`, `reasoning` resources now use strongly-typed request/response DTOs instead of `serde_json::Value`.
- Additional DTO modules shipped for `reviews`, `action_reviews`, `webhook_actions`, `control`, `ilp`, `cdl` — the corresponding resource clients continue to accept `serde_json::Value` for now; typed method signatures will land in 0.2.0 without breaking the wire contract.

#### Testing

- 41 tests passing: 18 unit tests (builders, errors, serialization round-trips for all tagged/untagged variants), 17 integration tests (wiremock — tenant headers, auth, retries, timeouts, path resolution, typed request/response round-trips), 6 doc tests.
- `cargo clippy --all-features --tests --examples -- -D warnings` clean.
- GitLab CI (`.gitlab-ci.yml`): on every push, runs `cargo build`, `cargo test` (default features and `native-tls`), `cargo clippy --all-features --tests --examples -- -D warnings`, `cargo fmt --all -- --check`, `cargo doc --all-features --no-deps` with `RUSTDOCFLAGS=-D warnings`, and `cargo publish --dry-run`. On `vX.Y.Z` tag push, verifies the tag matches `Cargo.toml`, re-runs tests, and publishes to crates.io using a masked `CARGO_REGISTRY_TOKEN` GitLab CI variable. All jobs run on `rust:slim` (latest stable).