Vivarium.Changeset
Reference .NET SDK for the vivarium-changeset spec: JCS canonicalization, fingerprinting, validation, unified diff, and authoring. No apply logic — the changeset is a contract, not an executor.
Install
| Product | Versions |
|---|---|
| .NET |
README
Vivarium.Changeset — .NET reference SDK
Construct, canonicalize, fingerprint, and validate Vivarium Changeset documents. Contains no apply logic — appliers (e.g. vivarium-stage) are consumers of this format, not part of this SDK.
No runtime dependencies beyond the BCL. Targets .NET 10. Same surface as the
TypeScript reference SDK; fingerprints are byte-identical
across the two (proven by the shared conformance fixtures, including the
interop-jcs-edges vector).
Usage
using System.Text.Json.Nodes;
using Vivarium.Changeset;
// the artifact's current source, and the source the agent proposes
var currentSource = "export function LoanScreen() { /* current */ }";
var nextSource = "export function LoanScreen() { /* renders dueDate */ }";
var doc = new ChangesetBuilder(
intent: "Add a due-date to the loan screen",
producedBy: "my-agent",
createdAt: DateTimeOffset.UtcNow.ToString("o")) // caller supplies the clock
.AddSchemaOp((JsonObject)JsonNode.Parse("""
{ "op": "field.add", "entity": "loan",
"field": { "name": "dueDate", "type": "date" },
"explanation": "Stores the loan's due date" }
""")!)
.AddUiPatch(
artifactId: "screen-loans",
baseContent: currentSource, // null for creation
newContent: nextSource, // review diff + base fingerprint are derived, never hand-written
explanation: "Renders the due-date field")
.Finalize(); // validates, stamps fingerprint — or throws with structured errors
Verifying on the consuming side. Unlike Finalize, these APIs report — they do not
throw; a conforming applier checks the results and refuses on failure (spec §7):
var result = ChangesetValidator.Validate(doc); // spec §8 layer 1 — structure, vocabulary, diff consistency
if (!result.Valid)
throw new InvalidOperationException($"refusing changeset: {string.Join(", ", result.Errors.Select(e => e.Path))}");
if (!ChangesetFingerprint.Verify(doc)) // spec §6 — content-addressed integrity
throw new InvalidOperationException("refusing changeset: fingerprint mismatch");
Recording a review. The approval record's fingerprint is taken from the document, never
passed in, so it names exactly what was reviewed; a document that was never finalized, or
changed after it was, is refused. The caller supplies the clock, as for createdAt:
var approved = ChangesetApproval.Add(
doc,
approvedBy: "[email protected]", // opaque to the SDK
approvedAt: DateTimeOffset.UtcNow.ToString("o"), // RFC 3339 date-time (spec §7)
comment: "Checked the due-date rendering"); // optional
// approved["approvals"][0]["fingerprint"] equals doc["fingerprint"] — approvals sit outside the hash
Which approvals an applier trusts, and where records are kept, are the applier's decision (spec §7) — this only builds a record the gate can check.
verified-diff@0 UI patches (spec 0.2)
Surgical edits ride as a strict-dialect unified diff instead of a full artifact
re-emission. ChangesetValidator.Validate covers the document-only layer; before
applying, an applier MUST run the base-supplied layer (spec §8 layer 2):
using System.Text.Json.Nodes;
using Vivarium.Changeset;
var baseContent = "const title = \"Loans\";\n";
var nextContent = "const title = \"Active loans\";\n";
var patch = new JsonObject
{
["profile"] = "verified-diff@0",
["artifactId"] = "screen-loans",
["baseFingerprint"] = ChangesetFingerprint.OfArtifact(baseContent),
["diff"] = VerifiedDiff.Create(baseContent, nextContent), // deterministic, fail-closed dialect (spec §5.2.2)
["newFingerprint"] = ChangesetFingerprint.OfArtifact(nextContent),
["explanation"] = "Rename the title only",
};
var verdict = VerifiedDiff.VerifyAgainstBase(patch, baseContent); // ①base fingerprint ② apply + result fingerprint
if (!verdict.Ok)
throw new InvalidOperationException("refusing patch: " + verdict.Errors[0].Message);
_ = verdict.NewContent; // exactly what the reviewer's diff described
Surface
| Type | Members |
|---|---|
JsonCanonicalizer |
Canonicalize, CanonicalBytes — RFC 8785 (JCS) |
ChangesetFingerprint |
Of, Stamp, Verify, OfArtifact, Prefix |
UnifiedDiff |
Create, Apply, ReverseApply |
VerifiedDiff |
Create, Apply, ParseStrict, VerifyAgainstBase — spec §5.2.2 dialect |
ChangesetValidator |
Validate, SupportedSpecVersions, BaseStateKinds |
ChangesetBuilder |
AddSchemaOp, AddUiPatch, AddVerifiedDiffPatch, AddDataPatch, ToDraft, Finalize |
ChangesetApproval |
Add — spec §7 |
Conformance
dotnet test runs the unit suite plus the shared spec/fixtures/
corpus — the same vectors the TypeScript SDK runs. The fixtures are generated by the
TypeScript reference implementation; this SDK reproduces them exactly.
Changes from Previous Version
Adoption Assessment
Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.