Most Graft workflows begin with source records and a contract, not an
existing knowledge store. graft_open() creates a blank
local store when its path does not exist. From there, candidate records
are checked in a read-only plan before one transaction accepts them as
revisions.
The accepted revision ledger is the source of record content and history. Current records, search indexes, supported graph relationships, and the Open Knowledge Format (OKF) working tree are read views built from that ledger. Snapshot views select those reads at one accepted commit boundary.
Swipe to explore the diagram →
From a contract to accepted knowledge
Start with a source contract
For related tables, start with data-dict. Graft maps its supported
tables, columns, primary keys, scalar types, enums, sensitivity
declarations, and foreign keys into a compiled .graft.json
contract. Planning validates the mapped foreign keys, but Graft does not
turn them into graph traversal edges.
Move to LinkML when the domain needs ontology identifiers, inheritance, polymorphic references, or semantic statements. An ordinary LinkML object reference is also a validation rule, not automatically a graph edge. The semantic graph projection is driven by classes that the compiled contract declares as graph-producing edges or semantic statements.
Both providers compile to the same runtime contract. A provider defines valid record meaning; it does not store accepted records or provide another mutation path. Contract compiler boundaries documents the provider-specific dependencies, supported profiles, and mapping limits.
Review a plan before writing
graft_plan() accepts named data frames and explicit
provenance. It normalizes values, resolves identity, validates the
complete candidate set, and compares the candidates with current
accepted heads. The result separates inserts, updates, matches, and
issues so a caller can decide whether the proposed change is
correct.
Planning writes no accepted records or provenance. The plan binds its result to the store identity, schema digest, expected record heads, idempotency state, and a deterministic digest. If any of those preconditions changes, the old plan cannot be committed.
Commit one checked plan
graft_commit() rechecks the plan, store, active
contract, write capability, idempotency state, and expected heads
immediately before mutation. Records, provenance, and identity decisions
commit in one transaction.
Each accepted revision retains its record content, predecessor, changed fields, schema digest, accepted batch, and producer provenance. Historical state comes from those accepted revisions rather than from logs or overwritten current tables.
Build read views from revisions
Graft derives current record heads, identifiers, search data, declared semantic relationships, and the OKF working tree from accepted revisions and the active contract. These views can be checked and rebuilt; they do not accept writes on their own.
That separation matters when a projection is stale or damaged: the accepted revision chain remains the recovery source.
What appears in the semantic graph
Graft does not infer graph meaning from every field that contains another record’s ID.
- A supported data-dict foreign key validates its concrete target.
- An ordinary LinkML object-reference slot validates its declared range.
- A LinkML class with a compiled edge or semantic-statement role contributes edges to the semantic graph projection.
- Narrative statements remain accepted, searchable knowledge but do not become semantic subject-predicate-object edges.
This keeps a database join, a validated reference, and a domain assertion from being treated as interchangeable. See Add graph semantics with LinkML for a working semantic-statement example.
Why Graft uses S7 at stable boundaries
S7 protects the objects whose invariants must survive across function calls:
-
GraftSchemaowns a validated compiled contract and its digests. -
GraftProvenanceidentifies the producer event and replay boundary. -
GraftCommitPlanowns the candidate change set and commit preconditions. -
GraftStoreowns store identity and private connection state. -
GraftSnapshotowns a serializable accepted commit identity. -
GraftViewbinds that snapshot to a live store for read-only retrieval.
Records remain data frames, candidate collections remain named lists, and retrieval results remain data frames or lists. Graft does not create an R class for every data-dict table or LinkML class; the compiled contract remains the domain type system.
DuckDB stays behind the package API
The current store uses embedded DuckDB, but public functions describe user operations: open, plan, commit, retrieve, inspect, and synchronize. No public function exposes internal table names or accepts raw SQL.
The store owns its connection, transactions, format version, migrations, and projection maintenance. A future backend change therefore need not change the public workflow.
Failed preconditions do not become partial changes
The package makes common failure states explicit:
- invalid candidates return collected issues and cannot commit;
- an altered plan fails digest verification;
- a changed contract or record head makes a plan stale;
- a transaction failure accepts none of the batch;
- an OKF edit remains a proposal until reviewed and committed;
- projection drift can be detected and repaired from revisions; and
- retrieval limits and truncation are reported.
There is no force flag that turns a failed precondition into acceptance. Create a new plan against the current state instead.
OKF is a readable working surface
Swipe to explore the diagram →
For code, start with Getting started. Continue with data-dict, change control, and retrieval. Add LinkML when the domain needs semantic graph behavior, and use open knowledge for the readable working surface.