Skip to main content
Release notes for the @visiq/harness SDK (and its Python peer visiq). The SDK is pre-1.0 (0.x): there is no wire-compatibility guarantee yet, and breaking changes may ship in any minor release until v1.0 GA. Pin an exact version and read the Breaking / Removed entries below before upgrading — see SDK versioning & compatibility for the full posture.
Canonical source. The registry version history is the authoritative record of what is live: npmjs.com/package/@visiq/harness. Check it rather than this page for the current build — these notes are hand-maintained and have run behind the registry before (0.2.7 and 0.2.8 published with no entry here). The package’s own CHANGELOG.md lives in the repo and is not shipped inside the tarball, whose files allowlist is dist, README.md and LICENSE.
Every minor may break at 0.x. A 0.x → 0.x minor bump is allowed to remove or rename a field, change a default, or tighten a shape. Don’t float a version range across a minor boundary in an unattended pipeline — pin, then upgrade deliberately after reading the entries below.

0.2.10

Metadata only — no runtime behaviour changed. The package description was rewritten onto one shape shared across the whole VisIQ harness/SDK family (npm, PyPI, Maven Central, RubyGems), so every package now describes itself in the current action-governance / retrieval-governance / audit-trail vocabulary. No API, decision, or wire change — a republish is required only because registry metadata is frozen at publish time.
Why this is 0.2.10 and not 0.2.9. The rewrite was authored against 0.2.9, but a concurrent promotion published 0.2.9 from a tree that did not yet contain it. A published version is immutable, so 0.2.9 on the registry carries the OLD description permanently and the rewrite needed the next number. The same collision hit @visiq/openclaw-plugin (0.1.100.1.11) and @visiq/claude-code-harness (0.1.50.1.6). NPM Content Freshness is the gate that caught it: it rebuilds each would-be-published tarball and compares its whole content hash against the registry artifact at the same version, so “edited but not bumped” fails a PR instead of silently no-op’ing at publish time.
0.2.7 and 0.2.8 shipped without an entry on this page. Their contents are in the git history; this note records the gap rather than reconstructing them.

0.2.6

Republish note. The security and compatibility changes below were merged after 0.2.5 was published (2026-07-12) but no version bump followed, so 0.2.5 on the registry does not contain them. 0.2.6 is the first published build that ships them. (Versions 0.2.10.2.5 are backfilled separately.)

Changed

  • Fail-closed on an unrecognized retrieval outcome (security). The retrieval application layer now withholds content — drops the document or returns the blocked sentinel — on any outcome verb this build does not recognize, instead of passing it through. This is defense-in-depth behind the engine’s own fail-closed mapping; allow / escalate passthrough is unchanged. An unaware upgrader gets strictly safer behavior.
  • Every control-plane request now carries X-VisIQ-SDK (version) and X-VisIQ-Dialect (wire-contract capability) headers. Telemetry only — not load-bearing for any decision.
  • MUST-UNDERSTAND bundle refuse. A rule bundle that declares a min_dialect newer than this SDK speaks is refused wholesale (fail-closed, deny-all) rather than partially applied. Dormant today (min_dialect is 1 everywhere); it is the forward-compatibility safety net for the first wire-contract bump. The refuse also lives in the shared engine (@visiq/core-wasm ^0.1.3) so every language binding enforces it uniformly.

Removed

  • Breaking — the @visiq/harness/record subpath export is removed. The audit layer is now a server-side proof layer only: every action and retrieval decision is automatically signed (Ed25519) and persisted by the backend. No SDK import is required to produce or read receipts — query the dashboard or the REST API instead. The previous types (RecordEnvelope, RecordSource, RecordDecisionPayload, SigningResult, ReceiptVerificationInput) have been deleted from the SDK.

Deprecated

  • The recall_receipts Postgres view is deprecated in favor of querying decision_receipts with source = 'recall' for complete, consistent views across all decision sources. The view is retained for backward compatibility and will be removed in a future release.

0.2.0

Added

  • AgentVendor union type ('visiq' | 'crowdstrike' | 'intune' | 'sentinelone' | 'unknown').
  • FleetInstance.last_scanned: string | null — ISO timestamp of the last per-instance heartbeat.
  • FleetInstance.agent_vendor: AgentVendor — vendor of the agent reporting heartbeats for the instance.
  • HeartbeatInput { instanceId: string; vendor: AgentVendor } input type for fleet.heartbeat().
  • HeartbeatResponse.instance_id — echoes the heartbeated instance id back to the caller.

Breaking

  • fleet.heartbeat() now requires a HeartbeatInput argument ({ instanceId, vendor }). Callers that previously invoked fleet.heartbeat() with no arguments must iterate fleet.status().instances and call once per instance.

Where to look next

Versioning & compatibility

The full pre-1.0 posture, the invariants held even at 0.x, and the v1.0 compatibility window.

SDK Reference

The visiq() surface, options, framework detection, and error behavior.