* Add the LogicSRC OpenContext specification OpenContext is an open specification for durable, portable, permissioned, provenance-aware context shared between humans and AI agents. It defines how organizational knowledge is described, authorized, versioned, resolved, audited, and handed between replaceable workers without losing institutional state. Follows the OpenPRD/OpenOntology pattern already in the repo: self-contained JSON Schemas in @logicsrc/schemas, a reference implementation package, CLI subcommands, docs, examples, and an OpenPRD record. Schemas (8, all self-contained so a third party can fetch one file and validate against it with no further resolution): manifest, object, bundle, role, provenance, decision, diagnostic, audit-event — registered in @logicsrc/validators and schemas:validate. Reference implementation (@logicsrc/opencontext): loader with upward manifest discovery, the full resolution pipeline, authority/supersession, permissions, redaction, lifecycle, provenance, deterministic digests, doctor, search, graph, history/diff, guarded writes, audit events, and file/http/git/sqlite adapters. CLI: all 15 specified commands, as a standalone `opencontext` binary and as `logicsrc context`, sharing one implementation so the two cannot drift. Design decisions worth noting: - Supersession is declared, never inferred from version numbers. Inferring it would hide the governance failure it represents and make multiple-active-versions and duplicate-canonical impossible to detect. - The bundle digest identifies the resolved context, not the moment it was computed, so generated_at/bundle_id/digest/as_of are excluded while objects, lifecycle states, exclusions and warnings are covered. That is what lets a decision record cite exactly the context that produced it. - A role's own max_classification beats an inherited one, so a ceiling on a shared base role cannot silently cap a role deliberately granted more; requesting several roles at once still takes the lowest, so combining roles never escalates. - Scope wildcards match whole dotted segments only. A trailing .* covers a subtree; an interior * matches exactly one segment. Substring matching here would be an access-control bug. - --include narrows an existing scope and is applied after it, never merged into it, so a request can never widen what a role holds. Verified: 226 tests across core primitives, permissions/redaction, the resolution pipeline, security, the published conformance fixtures (13 valid, 35 invalid, 8 resolution scenarios), project behaviour, and the five shipped examples — which are held to --strict and a 100% health score. Benchmarks meet every published budget (resolve 1,000 objects in ~33ms against a 2s target). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Point install docs at @logicsrc/opencontext; record the npm name collision The unscoped `opencontext` name is already published on npm by an unrelated third party (federicodeponte/opencontext, 2.0.0), so `npx opencontext` would install a stranger's package. Docs now use `npx @logicsrc/opencontext`; the bin stays named `opencontext` so the command reads as the PRD specifies once installed. Recorded in PRD 0003 as a blocker to resolve before any publication, along with the fact that no @logicsrc spec package has ever been published, so there is no existing release path to slot into. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Advance the logicsrc-mcp next-PRD-id assertion to 0004 standards.test.ts asserts prd_next_id against the live prd/ directory, so adding PRD 0003 makes the next free id 0004. The test's own comment anticipates this: "advances with every PRD added". Caught by CI, not locally — the earlier verification ran per-package tests for the packages this branch touches, and logicsrc-mcp is coupled to the PRD directory without importing from it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.4 KiB
Context object reference
One durable unit of context: a mission statement, a policy, an SOP, a customer fact, a decision, a piece of operational state.
Schema: https://logicsrc.com/schemas/opencontext/object.schema.json
Only id and type are required. Everything else exists so context can be governed rather than merely stored.
Three ways to write one
Markdown with front matter — metadata in the fence, prose as content. The usual choice.
---
id: policies.refunds
type: policy
layer: L3
title: Refund policy
authority: canonical
owner: support
updated: 2026-08-09T00:00:00Z
---
Refund requests are accepted within 30 days of purchase.
YAML or JSON — the whole document is the object. Use this when content is structured.
{
"id": "customers.acme",
"type": "customer",
"content": { "name": "ACME Inc.", "plan": "enterprise" }
}
Markdown with no front matter — still a valid object. The body is the content, and the collection supplies id and type. This is what makes OpenContext adoptable: point it at an existing docs/ folder and it works, then add metadata where governance actually matters.
Identity
| Field | Notes |
|---|---|
id |
Required. Stable, unique in the namespace. Dotted lowercase. Renaming is a breaking change — prefer supersession. |
type |
Required. Open vocabulary: mission, policy, procedure, decision, product, customer, knowledge, note… A validator must not reject an unknown type. |
layer |
L0–L5. Describes the kind of knowledge, never its authority. |
title |
Short heading. Used by search, ranking, and Markdown rendering. |
summary |
One or two sentences. A resolver may compile this instead of full content when minimising context. |
Content
| Field | Notes |
|---|---|
content |
Inline. A string for prose; an object or array for structured data. |
content_type |
e.g. text/markdown, application/json. |
content_uri |
Where content loads from when not inline: file://, http://, https://, git://, sqlite://, or any scheme an installed adapter claims. |
An unknown scheme fails clearly. It is never resolved to empty content — a bundle that silently omits the pricing it was asked about is worse than an error, because nothing looks wrong.
OpenContext does not assume all context is prose.
Authority and trust
authority: canonical
trust: trusted
authority — how much this counts as truth. Declared by the owner of the context, never inferred from retrieval rank, recency, or what the content says about itself.
| Level | Meaning |
|---|---|
canonical |
The organization's own source of truth |
approved |
Reviewed and sanctioned |
reference |
Useful, not binding |
observed |
Seen in the wild, unverified |
inferred |
Derived by a model or heuristic |
historical |
Retained for the record only |
Default when omitted: reference.
trust — where the content came from, in terms of whether it can be believed.
| Level | Meaning |
|---|---|
trusted |
Authored inside the trust boundary |
verified |
External but integrity-checked |
untrusted |
Arrived from a system that can carry attacker-controlled text |
These are different axes. An object can be authority: canonical about a fact while the fact's content is trust: untrusted — and that combination is a validation error, because canonical means the organization vouches for it, and you cannot vouch for text a stranger typed into a form.
Ownership and approval
| Field | Notes |
|---|---|
owner |
Accountable role, team, or identity. doctor reports unowned objects, because unowned context is what goes stale. |
status |
draft, pending, approved, rejected, retired. Drafts and pending objects are excluded from default resolution. |
approval |
Requirements and recorded approvals. An object requiring two approvals and carrying one is not approved. |
review |
Cadence. Overdue reviews are reported. |
approval:
required: true
roles: [legal, executive]
minimum: 1
approved_by:
- role: legal
id: counsel@example.com
at: 2026-08-08T10:00:00Z
Time
| Field | Notes |
|---|---|
created |
RFC 3339. |
updated |
RFC 3339. Freshness is measured from here. |
valid_from |
Object is future and excluded before this instant. |
expires |
Object is expired after this instant. Explicit null means never expires — different from omitting the field. |
ttl |
Per-object staleness window, overriding freshness.default_ttl. |
durability |
ephemeral, session, operational, long-lived, permanent. |
Lifecycle state is always computed against a timestamp and never stored. See lifecycle.
Access
classification: internal
permissions:
read: [sales-agent, finance-agent]
write: [sales-admin]
deny: [contractor]
redact:
- path: ssn
mode: remove
classification is one of public, internal, confidential, restricted, and bounds who may read the object regardless of scope.
permissions.read narrows a role that would otherwise include the object. deny overrides everything. An absent read list means the repository scope rules decide.
Read access never implies write access.
Relationships
| Field | Notes |
|---|---|
supersedes |
Objects this replaces, as id or id@version. |
superseded_by |
Set on the older object when the chain is written explicitly. |
conflicts_with |
Objects known to contradict this one. |
references |
Context this cites. Drives the graph and orphan detection. |
depends_on |
Context that must resolve alongside this for it to make sense. |
applies_to |
Roles, agents, products, or scopes this is about. The strongest relevance signal, because it is the author saying explicitly what the context is for. |
Every reference must point at something that exists. A broken chain silently resurrects retired policy, so it is an error rather than a no-op.
Provenance
canonical_source: true
or
sources:
- uri: git://github.com/acme/context/policies/refunds.md
type: document
retrieved_at: 2026-08-09T15:00:00Z
digest: sha256:9f2c…
trust: trusted
canonical_source: true says this object is the origin — a mission statement written here has no upstream. Anything mirrored from another system should name it. See provenance.
Confidence and tags
confidence: 0.6
tags: [pricing, enterprise]
confidence breaks ties within an authority level. It never promotes an object across levels — a model that is 99% sure does not thereby outrank a reviewed policy.
Extensions
extensions:
com.example.risk:
score: 0.25
Reverse-DNS namespaced. Preserved through resolution and into the bundle.
Full example
id: pricing.enterprise
type: policy
layer: L3
title: Enterprise Pricing
content: |
Enterprise plans start at $2,500/month.
authority: canonical
owner: sales
version: 3
created: 2026-07-01T00:00:00Z
updated: 2026-08-09T00:00:00Z
valid_from: 2026-08-01T00:00:00Z
expires: null
durability: long-lived
classification: internal
permissions:
read: [sales-agent, finance-agent]
write: [sales-admin]
sources:
- uri: crm://pricing/enterprise
type: canonical-record
supersedes:
- pricing.enterprise@2
confidence: 1.0
tags: [pricing, enterprise]
Decision records
A decision is an ordinary context object with type: decision and a few extra fields. Schema: https://logicsrc.com/schemas/opencontext/decision.schema.json.
id: decisions.2026-08-09-model-provider
type: decision
layer: L5
title: Default model provider
authority: approved
owner: platform
status: accepted
decision: Use provider X as the default runtime.
rationale:
- latency
- cost
- reliability
alternatives:
- option: provider Y
rejected_because: no EU region
consequences:
- Re-evaluate at renewal.
approved_by:
- role: CTO
bundle:
bundle_id: ocb_37c04d801d013b07
digest: sha256:37c04d80…
created: 2026-08-09T15:00:00Z
status for a decision is proposed, accepted, rejected, superseded, or deprecated.
The bundle block is what makes a decision auditable rather than merely recorded: citing the digest lets a reader prove which context was — and was not — in front of the decider. Reversing a decision supersedes it; it does not delete it.