0.2.0 — 2026-05-05 (breaking)
API shape
- All public ops now have two variants:
new/1,compose/3,combine/3,harmonise/4,graft/3return{:ok, %Artefact{}} | {:error, error}.new!/1,compose!/3,combine!/3,harmonise!/4,graft!/3return%Artefact{}directly or raise the error struct. Behaviour matches 0.1.5's raise-everywhere — the!variants are the gentle migration path.
validate/1shape::ok | {:error, %Artefact.Error.Invalid{reasons: [...]}}(was{:error, [reason_strings]}).validate!/1raisesArtefact.Error.Invalid(wasArgumentError).- Closes #23, #25.
Errors as structured values
- New
:sploderuntime dependency ({:splode, "~> 0.3"}). Artefact.Error— Splode root with two error classes (:invalid,:operation).Artefact.Error.Invalid— validation rule violations;:reasonsfield carries the list of human-readable strings.Artefact.Error.Operation— op-specific outcomes;:op,:tag,:detailsfields. SeeMIGRATION.mdfor the full per-op tag table.- Errors are real Elixir exceptions — raisable by the
!variants, pattern-matchable as struct values from the non-!variants, and aggregatable by Splode-using callers (e.g. UsTwo libraries).
Module reorg (internal)
Artefact.Op— implementation home for the operations.Artefact.Validator— implementation home for validation rules; surfaced viadefdelegatefromArtefact.- The
Artefactmodule is now a thin macro facade plus the%Artefact{}struct definition. Future internal refactors won't churn the consumer-visible surface.
Migration
See MIGRATION.md for the migration guide. TL;DR — append ! to every op call and you're done; use the non-! variant + with/case if you want explicit error handling.
0.1.5 — 2026-05-05
Artefact.is_artefact?/1,Artefact.is_valid?/1,Artefact.validate/1,Artefact.validate!/1— public validation API. Closes #26, #27Artefact.UUID.valid?/1— UUIDv7 format predicate; used internally by validation and exposed for callers- All public ops (
new/1,compose/3,combine/3,harmonise/4,graft/3) now validate their input artefacts and validate the produced artefact before returning — corruption fails at the call site rather than several steps downstream. Closes #30 (empty/invalid uuid rejected at op input), #24 (non-list:labelsrejected at op input) Artefact.graft/3enforces the no-new-islands rule — every new node inargsmust reach a bind-only key viaargs.relationships; raisesArgumentErrorlisting orphan keys otherwise. Closes #29- Validation rule-set: artefact uuid is UUIDv7; node uuid is UUIDv7; node
:labelsis a list of strings; node:propertiesis a map; relationship:typeis a non-empty string; relationship:from_id/:to_idreference an extant node; node uuids, node ids and relationship ids are unique within the graph
0.1.4 — 2026-05-05
Artefact.graft/3— pipeline-friendly convenience for extending an artefact with new nodes and relationships declared inline (same shape asArtefact.new); every node in args MUST carry:uuid(no auto-find — uuid is the binding); nodes whose uuid lives in left bind to it (labels unioned, properties merged left-wins), nodes with new uuids are added; opts honour:titleand:description; raisesArgumentErrorfor missing uuid, duplicate keys, or relationship referencing an unknown key; records:graftedprovenance source
0.1.3 — 2026-04-30
Artefact.Mermaid.export/2— derives Mermaidgraphsource from an%Artefact{}, alongsideArtefact.CypherandArtefact.Arrows; nodes render as circles,:directionoption for:LR,:RL,:TB,:BT,:TD:descriptionfield on%Artefact{}— optional human-readable description, defaults tonil; accepted byArtefact.new/1and round-tripped throughArtefact.Arrows- Mermaid front-matter
title:(Mermaid 9.4+ heading) and bodyaccTitle:derived fromartefact.title;accDescr:derived fromartefact.description(inline form for single-line, block formaccDescr { ... }for multi-line) Artefact.combine/3— pipeline-friendly convenience overArtefact.Binding.find/2+Artefact.harmonise/4; the heart flows through the pipe as the first argument, opts honour:title,:base_labeland:descriptionoverrides; raisesMatchErrorwhen no shared bindings exist
0.1.2 — 2026-04-21
- Improved
Artefact.new/1macro — nodes and relationships declared inline with atom keys and keyword options Artefact.Cypher.merge_params/1— parameterised MERGE returning{cypher, params}for driver useArtefact.Cypher.create_params/1— parameterised CREATE returning{cypher, params}Artefact.Binding.find/2— finds shared nodes between two artefacts by uuid for harmonisationArtefact.harmonise/3macro — merges two artefacts on shared node bindings; left argument is heartside
0.1.1 — 2026-04-01
Artefact.Arrows— lossless round-trip with Arrows JSON (from_json/2,to_json/1)Artefact.Cypher— inlinecreate/1andmerge/1Cypher string generation%Artefact{},%Artefact.Graph{},%Artefact.Node{},%Artefact.Relationship{}structsArtefact.compose/2— combines two artefacts into one graph