3.7 KiB
Content References
Date: 2026-05-04
Purpose
Content references are the first WP-0010 extension layer. They give Markitect a shared way to name and resolve Markdown content units without changing the existing parser, query, transform, compose, include, contract, or cache APIs.
The goal is a small resolver that later features can reuse:
- includes can accept references as well as paths
- explode/implode can write manifests with stable unit IDs
- processors can receive typed units and dependency edges
- tangle/weave can address chunks and generated outputs
- cache and access-control backends can index the same IDs
Reference Syntax
References are compact strings:
path/to/file.md
path/to/file.md#section:introduction
path/to/file.md::sections[heading=Decision]
std:clauses/payment.md
std:clauses/payment.md#payment-terms
std:clauses/payment.md#region:boilerplate
std:clauses/payment.md#tag:legal
#local-section
The parts are:
namespace:: optional namespace declared in frontmatterpath: a Markdown file path relative to the current document, or relative to the namespace target#fragment: optional unit lookup inside the target document::selector: optional existing Markitect query selector
Fragments and selectors are mutually exclusive during resolution. Selectors are delegated to the existing query engine, which keeps this layer small and avoids inventing a second query language.
Namespaces
Namespaces live in Markdown frontmatter:
---
namespaces:
std: ./standard
product: ../product-docs
---
Namespace keys may be written with or without a trailing colon. Namespace values are string paths. Relative namespace paths resolve under the resolver root. All resolved file paths must stay inside that root.
Content Units
The resolver currently emits these unit kinds:
document: full Markdown filesection: heading-led Markdown sectionheading: heading line- existing query kinds such as
frontmatter,block,metrics, orsection
Each unit includes:
unit_id: stable local IDkindsource_path- source line span when available
namecontent_hash- raw text
- metadata from the source or query match
Heading and section IDs use an explicit trailing heading ID when present:
## Payment Terms {#payment-terms}
Otherwise the resolver derives a slug from the heading text and adds numeric suffixes for collisions.
Named regions use HTML comments so they can live in Markdown and many source files without changing the rendered document:
<!-- mkt:region id="boilerplate" tags="legal reuse" -->
Reusable text.
<!-- /mkt:region -->
Fenced blocks can be addressed when their info string includes an ID:
```python {#load-config tags="code setup" tangle="src/config.py"}
def load_config():
return {}
```
Supported fragments now include:
#section:<id-or-heading-slug>#heading:<id-or-heading-slug>#region:<id>#fence:<id>#tag:<tag>#line:<start>or#line:<start>-<end>#<id>as a convenience lookup across sections, regions, fenced blocks, and headings
CLI
Resolve a reference from a context document:
mkt ref resolve examples/references/context.md 'std:clauses.md#payment-terms'
JSON and YAML formats include the resolved text and metadata:
mkt ref resolve examples/references/context.md 'std:clauses.md::sections[heading=Warranty]' --format json
Extension Boundary
This layer is intentionally read-only. It does not replace mkt include,
mkt query, or mkt extract. Instead it defines the address model those tools
can adopt when their next WP-0010 tasks require richer content identity,
processor dependencies, source maps, and reversible manifests.