FABRIC-SPEC v0 — the Governed Knowledge Graph as a port set
Status: v0 draft for spoke-owner review · July 2026 Comment deadline and reviewer list set at circulation. Written comments resolve into v0.1 as superseding sections — never silent edits. Normative language: "must" / "never" statements are binding on implementations; descriptive text explains the reference implementation.
0. What this is, and what it deliberately is not
Every DIE spoke needs the same thing from the center: a place where engagement knowledge, work in flight, and produced artifacts live with provenance, so that today's engagement becomes tomorrow's context. The DIE map calls this the Governed Knowledge Graph — the Fabric. This document specifies the Fabric as a port set: a small set of interfaces with exact contracts, which any storage technology can implement as an adapter.
It deliberately does not pick a database. The graph is a property of the contracts — typed artifacts, canonical subjects, explicit links, provenance stamps — not a property of a graph database. Specify the ports well and the knowledge graph emerges from any conformant backend; a graph engine then becomes one adapter (or an index over another adapter) rather than a prerequisite. This is the same ports-and-adapters discipline that recently let the marketplace site move from a local development environment into Snowflake App Runtime with changes confined to the adapter layer.
A running reference implementation exists (the assessment/research/collateral "brigade house," filesystem-backed). It exercises this spec end to end, and §7's conformance checklist grades it honestly — including the places where v1 conformance is deliberately partial. Where this spec's neutral vocabulary differs from the reference implementation's names, the mapping is:
| Spec term | Reference name | Spec term | Reference name |
|---|---|---|---|
| Fabric store | cellar | capability manifest | menu |
| work queue | rail | intake role | steward |
| work item | ticket | station | station (unchanged) |
| producing capability | brigade | Gate B | phase-0 |
Conformance (§7) is checked against field semantics under this mapping — the reference implementation writes produced_by.brigade where this spec says produced_by.capability; either naming is v0-conformant, and v0.1 will pick one.
The two planes. The Fabric is one substrate with two contracts, deliberately separated:
| Plane | Holds | Lifecycle |
|---|---|---|
| Store | Knowledge of record: landed artifacts, filed work items, capability manifests, source material | Append-only, forever |
| Queue | Work in flight: open work items under lease | queued → leased → terminal, then filed to the store |
The queue is hot and small; the store is cold and permanent. A work item lives on the queue only while open; at terminal close it files to its subject in the store, so the queue never becomes an archive.
1. Store layout
1.1 Sections and natural keys
Top level partitions by what kind of thing; the folder inside is the thing's natural key:
<fabric-root>/
companies/<canonical-id>/ # research subjects: identity note · <kind>/<date>-artifact · tickets/ (filed)
assessments/<subject>/ # assessment records, contracts, manifests, collateral, publish records
capabilities/<name>/ # per-capability knowledge: capability manifest, roster notes
competencies/<domain>/ # source material that skills and assessments are built from
(The reference implementation also co-locates the queue's storage as a rail/ section here; that is a filesystem convenience, not required layout — queue storage is backend-specific, and §8.1's queue is a table.)
1.2 Canonical subject identity
subject is a canonical key minted once per real-world entity — one entity, one key, however many spellings arrive. Identity resolution happens at intake, before any work item is written, and is recorded in an identity note (companies/<id>/identity.md: canonical name, known aliases, resolution provenance). Duplicate subjects are an intake defect; merges are recorded in the identity note, never silently.
1.3 Landing contract
The store exposes four operations: land(artifact, meta) → ref · resolve(ref) → content · search(query, filter) → refs · list(filter). Landing requires frontmatter meta:
| Field | Meaning |
|---|---|
landed |
ISO timestamp |
kind |
artifact type, from the producing capability's manifest (§3) |
subject |
canonical key (§1.2) |
produced_by |
{capability, work-item, station} — who made it, under which order. A station is one execution agent with one narrow job inside a capability (e.g. a spec author, a test author, a builder, a critic); recording it makes provenance reach inside the production line. |
supersedes |
null, or the ref this replaces (§1.4) |
provenance |
original source description |
A deterministic land-time lint enforces this (required fields present, subject matches the canonical-key convention, supersedes resolves). A failing artifact does not land — it bounces to its producer.
1.4 Append-only + supersedes chains
Landing never overwrites. A re-land of the same subject/kind lands beside the old artifact under a new date-stamped name, with supersedes pointing back. Readers resolve "current" by following the chain to its newest link. Consequences: history is never destroyed, "what did we believe on date X" is always answerable, and correction is itself a recorded event.
1.5 Refs and links
A ref is a backend-relative path (companies/acme/jobs/2026-07-02-snapshot.md) — stable across backend moves. Cross-artifact links are by stable name, not path, so reorganizing storage breaks nothing. Frontmatter is the query plane (every artifact answers subject/kind/produced_by); links are the connection plane. This pair is what makes the store a knowledge graph: typed nodes (artifacts with kind + subject) and typed edges (produced_by, supersedes, explicit links) that any indexer — lexical, vector, or graph engine — can materialize.
2. Work-item envelope
A work item (reference name: ticket) is one mutable, append-only document that starts as the order and ends as the full build record. It is the only thing that crosses between the requesting side and the executing side — which is what lets those sides run in different runtimes.
2.1 Envelope fields
| Field | Type | Required | Notes |
|---|---|---|---|
ticket |
kebab-case string | ✔ | work-item id, unique on the queue |
artifact |
string | ✔ | a type the target capability's manifest offers (§3) |
status |
enum | ✔ | queue status: queued · leased · in-build · needs-context · escalated · done · killed |
requested_by |
string | ✔ | who placed the order |
subject |
string | optional, recommended | canonical store key; where the closed item files. When absent, derivable from the first store-typed context source. |
use_case |
string | optional | use-case catalog entry the request was paired to (reference field name: menu) |
type_hint |
enum | optional | computational · corpus · generative · operational · advisory |
lease |
null / object | shape-checked | {worker, at, ttl_min} while being worked |
context |
list, ≥1 | ✔ | typed pointer sources, each {id, type, ref, when}. Required minimum types: file · url · store. Deployments register more — the reference registers an mcp type and a local-search query type; a graph type is reserved, unimplemented. |
Body: four fixed sections, in order — Order (intent + scope + what done looks like) · Resolved-context snapshot (what each source resolved to at build time — append-only) · Work log (one timestamped entry per event: enqueue, lease, gate verdicts, station hops, every routing decision with rationale, terminal close) · Artifacts (refs to outputs).
2.2 Gate A — deterministic lint, enforced on both sides
Eight rules, checkable by script, run at enqueue (submitter side) and at pull (executor side):
- Work-item id present, kebab-case, unique on the queue.
artifactis a type the target capability's manifest offers (discovery items are universal).statusin the enum;leasenull unless leased/in-build, well-formed when set.contexthas ≥1 source; every source carriesid, type, ref, when; everytypeis registered.- Every eager source (
whenstarting "always") resolves at enqueue — no dead pointers get hung. - Order section present and non-empty.
- All four body sections exist, canonically named, in order.
- Pointers only — no inline content copies in
context; resolved content belongs in the snapshot, written at build time.
Failure at enqueue bounces to the submitter with failing rule numbers. Failure at pull is logged and the item parked needs-context as a flagged defect — the same check passing on one side and failing on the other means an adapter mutated the item in transit. The contract is enforced on both sides of the port precisely to make that class of defect visible.
2.3 Gate B — sufficiency judgment
After Gate A, the executor reads the Order plus eager sources and returns one of three verdicts: Clear (intent derivable without guessing; sources carry the substance the work type needs — e.g. worked examples with known answers for computational work, exemplars for generative work) → proceed. Ambiguous (the Order plausibly describes more than one deliverable, or sources contradict scope) → back to the submitter with specific questions. Thin (intent clear, named context missing) → back with an itemized list of what's missing and how it would sharpen the build. Gate A is schema truth a script checks; Gate B is judgment an agent makes. Folding them together yields either checkbox theater or buried mechanical failures — they stay separate.
2.4 Status vs phase — two lifecycles, never conflated
Queue status (frontmatter) is a queue concern: it is the only field a queue adapter reads. Build phase (which station the work is at) is an executor concern and lives in the work log. The queue never parses the work log. This separation is what keeps queue backends simple enough to swap.
2.5 Exits and loop budgets
Routing decisions close over a fixed exit set: advance · refire-to-author · reroute-to-spec · reroute-to-steward · kill. The names carry the reference implementation's station vocabulary: refire-to-author re-runs the building station against existing spec and tests; reroute-to-spec restarts from the specification station; reroute-to-steward returns the item to the intake role (reference name: steward — the front-of-house function that pairs requests to capabilities, gathers context, and writes work items). Escalate-to-human is a pause state, not an exit.
The two loops have distinct budgets, both mandatory: the context loop (reroute-to-steward → repair → re-enqueue) must have a configured bounce budget (reference: 3), after which the item returns to its requester — insufficient context is ultimately the requester's to fix. The build loop (refire/reroute among stations) must have a configured round budget, at which point the item escalates for a human's exit call rather than burning rounds silently.
3. Discovery — capability manifests
Each producing capability publishes a capability manifest (reference name: menu): the artifact types it offers and, per type, what a work item must carry (payload requirements, oracle/exemplar expectations, expected Order shape). Each offered type opens with a machine-parseable **Status:** live|planned marker — lint and submitters discover live types from the marker; it is contract, not decoration.
Source vs publication. The manifest SOURCE is versioned with the capability's code (a capability-changing release that doesn't touch its manifest isn't done). The PUBLICATION is the Fabric copy at capabilities/<name>/, produced by a discovery work item: a standard item (artifact: menu) the capability answers by introspecting itself and publishing, version-bumped, hash-stamped against the source. Freshness is checked, not assumed — a readiness check recomputes the source hash and warns on mismatch, with "re-run discovery" as the remedy. Discovery items close and file like any other work item, with subject = the capability's own key (capabilities/<name>), so the store accumulates an audit trail of capability change over time. (Precedent: MCP tools/list, A2A agent cards — discovery as a first-class, versioned answer.)
The envelope (§2) is infrastructure-owned and universal; manifests are capability-owned and specific. Intake roles bind to the envelope + queue + manifests, never to a capability's internals — which is what lets N intake surfaces serve M capabilities over shared queues.
4. Provenance and snapshot rules
- Everything landed says who made it and under what order (
produced_by). Any artifact can be traced to the work item that ordered it, and that item's work log shows every verdict and decision on the way. - Live sources are snapshotted at build time. A work item's context is pointers (Gate A rule 8); when a live source (url / mcp / query types) is resolved, the exact content resolved-to is recorded in the item's snapshot section. Same item, same build — replayable; a re-resolve is a new snapshot, visibly.
- Append-only everywhere. Queue status and lease advance; snapshot, work log, and artifact sections only grow; store landings supersede, never overwrite. History is never destroyed.
- Human approvals are recorded facts. Where a deployment's gate policy requires human sign-off, the approval (approver + provenance, including any delegation) is recorded on the work item — pre-recordable at enqueue so execution doesn't stall, while a missing or malformed approval still hard-stops. (This rule generalizes the reference implementation's assessment-gate practice; the envelope carries it, deployment policy decides where it applies.)
5. Close-out
At terminal close (done/killed) the work item files to its subject in the store — filing is a side-effect of the terminal ack at the queue port, so the queue is clear from that instant. Delivery back to the requester is the intake role's job, mechanized as a sweep: scan recently filed items for terminal status without a close-out signature, deliver the result on the intake channel, and sign the item. The signature is the whole mechanism — it completes the record, marks idempotency (signed items never re-deliver), and its absence is the retry queue. No event bus, no daemon watching the store: truth lives on the work item, and there is no second store to reconcile.
6. Queue port (normative summary)
Operations: enqueue · pull(worker) · ack(id, exit) · release(id) · read(id) · append(id, entry) · list(filter).
Pull leases atomically where the backend allows (§7 graded honesty) and must honor worker scope on shared queues: a puller declares the artifact types it serves and its capability name (so universal discovery items match by subject) — out-of-scope items are skipped untouched, never leased or judged. (A post-incident amendment: an unscoped puller once leased a foreign item and mis-parked it; scope made that structurally impossible.) Leases carry a TTL; an expired lease is visibly reclaimable, with the reclaim recorded on the work log. needs-context items are workable only by intake; escalated only by a human.
Ack maps exits to terminal or parked statuses — this mapping is normative for backends:
| exit at ack | resulting status | side-effect |
|---|---|---|
advance |
done |
lease cleared; file to subject (§5) |
kill |
killed |
lease cleared; file to subject (§5) |
reroute-to-steward |
needs-context |
lease cleared; stays on queue for intake |
| escalate (pause) | escalated |
lease cleared; stays on queue for a human |
refire-to-author and reroute-to-spec are executor-internal — they route between stations within a lease and never reach the queue port.
7. Conformance — what makes a backend a Fabric backend
A backend team can self-assess against this checklist. The evidence column cites what ships with the reference implementation — its contracts and adapter test suite — rather than deployment history.
| # | Requirement | Reference evidence (contracts + shipped tests) |
|---|---|---|
| C1 | Store partitions by kind with natural keys; canonical subject identity minted at intake | Store contract §subject-identity; identity-note convention with alias + merge provenance |
| C2 | Land-time deterministic lint; failing artifacts bounce, never land | cellarLint() in the shared adapter library, called on every land |
| C3 | Append-only with supersedes chains; readers resolve current via the chain | Store contract §landing; supersedes-resolution covered in adapter tests |
| C4 | Work-item envelope semantically as §2.1 (under the §0 name mapping), four body sections | Ticket contract (the single source of truth for the envelope); conformance enforced mechanically at enqueue and pull |
| C5 | Gate A (8 rules) enforced at enqueue AND pull | ticket_lint in the shared adapter library, invoked at both call sites; per-rule tests incl. negative controls |
| C6 | Gate B three-verdict sufficiency judgment before execution | Executor procedure (reference name: phase-0) with written Clear/Ambiguous/Thin criteria |
| C7 | Queue ops with lease/TTL/reclaim; status-vs-phase separation; worker scope on shared queues | Shared adapter library v1.1.0; scope behavior covered by tests written from an observed mis-pull |
| C8 | Capability manifests with Status markers, source-vs-publication split, hash-stamped freshness | Manifest contract; readiness check recomputes source hashes (manifests published per capability in the reference deployment) |
| C9 | Provenance meta on every landed artifact; build-time snapshots of live sources | Landing meta contract; snapshot section required by the envelope |
| C10 | Close-out: file-at-terminal-ack, sweep, signature-as-idempotency | find_unclosed() scan in the shared adapter library, with signature-format tests |
| C11 | Recorded human approvals (incl. pre-recorded at enqueue) that hard-stop when missing | Pre-signature contract in the assessment capability; missing-approval-escalates covered by its test suite |
| C12 | Search over the store (lexical at minimum) serving intake's gathering step | Store contract names search a first-class op; reference deployment indexes the filesystem store lexically + vectorally |
Graded honesty: the reference implementation's lease is advisory (no compare-and-set on a filesystem) — it runs one puller per capability by convention and uses the lease to detect violations. That is conformant for single-operator deployments only; C7 requires real atomicity the moment pullers multiply. This is a documented constraint, not a surprise — and it is the first thing the Snowflake backend fixes.
8. Backend sketches
8.1 Snowflake (the governed/enterprise target)
| Port | Snowflake binding |
|---|---|
| Store | Stage-resident artifacts + an artifact table (VARIANT payload + thin typed spine: subject, kind, landed, produced_by, supersedes as typed columns — the marketplace catalog's existing data-model decisions apply directly) |
| Store search | Cortex Search over the artifact corpus (search is an adapter concern, paired with — not replacing — the store of record) |
| Queue | Work-item table; pull = transactional UPDATE … WHERE status='queued' LIMIT 1 → real compare-and-set leasing, the multi-operator upgrade §7 requires |
| Discovery | Manifests land like any artifact; freshness hash in the spine |
| Why here | RBAC, audit, client data-gravity; and the site/marketplace consumption layer already runs Snowflake-native (App Runtime), so store-side landing puts producer and consumer in one governance domain |
Open questions for the companion Snowflake design note: stage-vs-table split per artifact size; snapshot storage for resolved live sources; whether Gate A lint runs as a stored procedure or client-side in the shared adapter library with the table as plain storage (lean: client-side — one lint implementation, N backends).
8.2 Neptune / AWS (the existing knowledge-graph work)
Our read — offered as a hypothesis for the Neptune-side working session to test, not as a conclusion: the existing AWS knowledge-graph work fits naturally as the graph-index adapter over the store, and it is arguably the best-positioned reader of §4's provenance model.
| Port | Candidate binding | Session question |
|---|---|---|
| Store (graph-as-index) | Artifacts remain in an object store (S3); Neptune materializes the graph the frontmatter already defines — nodes = artifacts (typed by kind/subject), edges = produced_by/supersedes/links |
What does the ingest path from store landings look like against the current graph schema? |
| Store (graph-as-store) | Artifacts as node properties/documents in Neptune | Open: do artifact bodies belong in the graph, or bytes-in-S3 with graphed metadata? |
| Queue | The queue's needs (atomic lease, mutable status) suggest pairing with a table/queue store; the two planes bind independently by design | Which AWS-side store gives the lease semantics §6 requires? |
| Discovery / provenance | Graph queries as the natural consumer of provenance edges ("everything produced under this engagement," "what superseded what") | Which existing graph queries map onto these directly? |
Where the current graph's schema wants fields this spec doesn't carry, those become v0.1 comments — the working session fills the fits-and-gaps table from the Neptune side.
8.3 What any backend must NOT do
Parse work logs for queue decisions (§2.4) · overwrite anything (§1.4; §4 rule 3) · accept inline context payloads (§2.2 rule 8) · publish capability manifests without a freshness stamp (§3) · deliver a result without signing the work item (§5).
9. Spoke view — who reads and writes what (illustrative)
Illustrative, not assignment: each spoke owner corrects their own row in v0.1 comments.
| Spoke | Writes to the Fabric | Reads from the Fabric |
|---|---|---|
| Assess | assessments, contracts, Build Manifests (the typed Assess→Data handoff artifact), collateral, publish records | company research, competencies, prior engagements |
| Data | build outputs, model/pipeline artifacts, delivery records | Build Manifests via store refs |
| Evals | evidence packages, eval records, regression baselines | artifacts under evaluation + their provenance chains |
| Registry | registered capability entries; skill artifacts with their build records | capability manifests (capability-published, per §3) + the discovery audit trail |
| Govern | gate policies, approval records | everything — provenance and approvals are queryable facts, not meeting minutes |
One store, five spokes, no bilateral integrations: each pair that needs to exchange value does it through a landed, typed, provenance-stamped artifact.
10. Known v0 boundaries
- Resolver port: the context-source entry schema is normative here (
{id, type, ref, when}, §2.1); the resolver's own operation set lives in the reference implementation's context-source contract and will be genericized as a v0.1 appendix. - Multi-writer store atomicity is backend-dependent; the filesystem reference relies on date-stamped names + land-time lint (§7 graded honesty covers the queue side).
graphresolver type is reserved, not implemented.- Per-deployment domain schemas (e.g. the Build Manifest) live in their deployments' repos as JSON Schema with both-sides validation — the Fabric carries them; it does not define them.