1. 摘要
本书定义 inkrail CLI 的人工制品边界、项目记忆、标准书架集成、书架本地构建调度、book-entry RDF12 投影、source set 新鲜度、Oxigraph 查询契约、内置查询动作、输出表面、错误语义和验证标准。
inkrail 面向 AsciiDoc 多书书架。它创建和识别标准书架,在项目配置中记录书架与书本,调度标准书架本地构建检查动作,按标准 profile 推导每本书的 book entry、documentRoot、RDF12 TTL、RDF12 JSON-LD 和 watch globs,在项目查询前强制刷新过期投影,并使用 Oxigraph 对单本书 RDF12 TTL 执行 SPARQL。
本书是设计规约,不是实现计划。它规定对象、契约和验收条件,使实现者和设计审查者能够在相同上下文中判断 inkrail 的行为是否成立。
前言
本书依赖三个事实来源。AsciiDoc 多书书架的标准结构来自 create-asciidoc-multi-book-workspace 默认模板。Book-entry parsing、origin source coordinate recovery 和 RDF12 投影来自 asciidoc-abundant-tree。查询语义由 AsciiDoc 书稿 RDF 投影查询工作流 定义。
inkrail 把查询动作放入带项目记忆和新鲜度约束的 CLI。它不复制查询教程,而是消费查询教程定义的动作、变量、排序和 source coordinate 语义。
本书不规定文件修改顺序、提交顺序或实现步骤。实现计划应以本书的配置契约、命令契约、状态机和测试契约为输入另行编写。
本书的 authored xref 使用受控关系谓词。rel=depends-on 表示源章节的对象定义依赖目标章节;rel=implementation 表示源命令表面实现目标查询动作;rel=documents 表示源章节说明目标对象的使用方法。
第一部:对象与问题世界
本部定义 inkrail 的人工制品身份、问题世界、设计坐标和对象边界。命令、配置和缓存只有在这些前提成立后才获得设计资格。
2. 人工制品身份
inkrail 是面向 AsciiDoc 多书书架的本地 CLI。
它创建和识别标准多书书架,在项目配置中记录书架与书本,调度标准书架本地构建检查动作,按标准书架规则推导每本书的 book entry、documentRoot、RDF12 TTL、RDF12 JSON-LD 和 watch globs,在项目查询前强制刷新过期投影,并使用 Oxigraph 对单本书 RDF12 TTL 执行 SPARQL。
inkrail 把标准书架、项目记忆、书架本地运行时、book-entry RDF12 投影和本地查询执行器组织为同一个项目命令表面。
该定义包含 inkrail 的构成性条件。缺少标准书架集成,inkrail 不能覆盖从空书架到可查询书稿的入口。缺少项目记忆,inkrail 只是普通 SPARQL runner。缺少投影新鲜度约束,inkrail 会把 stale projection 作为当前答案。缺少单书查询边界,inkrail 会过早进入跨书联合图问题。缺少 TTL-only mode 和 explicit projection mode,inkrail 会把临时实验强行纳入项目配置。
inkrail 的核心消费者是维护 AsciiDoc 多书书架的作者和开发者。作者使用它查询当前书稿的标题结构、交叉引用网络和审计事实。开发者使用它验证书稿投影、查询模板和 CLI 契约是否一致。
inkrail 的直接输出不是书稿内容本身,而是可观察投影。RDF12 TTL 是面向查询引擎的投影。RDF12 JSON-LD 是面向结构化消费者的投影。pretty 输出是面向终端读者的投影。JSON 输出是面向机器、脚本和大语言模型的投影。
inkrail 的完成条件不由命令存在决定。只有当项目记忆、标准书架 profile、书架本地构建调度、source set 新鲜度、投影刷新、查询执行、输出表面、错误语义和验证标准共同成立时,inkrail 才作为该人工制品成立。
3. 问题世界
AsciiDoc 多书书架由 catalog.adoc、books/、shared/、tools/adoc-books.mjs、包元数据和生成物组成。每本书拥有自己的 books/<book-id>/book.adoc、章节顺序、资源边界和网页产物。
标准书架的 book entry 位于:
books/<book-id>/book.adoc
asciidoc-abundant-tree 能读取 book entry 和 documentRoot,构造 source-aware RDF 1.2 标题投影图。rdf12 输出是 Turtle 文件,rdf12-json-ld 输出是 JSON-LD 文件。Turtle 文件可以被 Oxigraph 加载并执行 SPARQL 查询。
作者需要反复执行以下动作:
-
选择目标 book。
-
解析 book entry 和 documentRoot。
-
生成 RDF12 TTL。
-
加载 TTL 并执行 SPARQL 查询。
-
根据查询结果读取 origin source file。
-
使用 path、heading line、line span、column、headline、selector 和 raw 修改源书稿。
-
修改源书稿后重新查询当前书稿事实。
该链条的主要摩擦来自对象关系的手动维持。标准书架提供 book entry 和 include graph。asciidoc-abundant-tree 提供 source-aware RDF12 投影。查询执行器加载 TTL 并执行 SPARQL。查询语句来自 查询工作流指南。查询结果提供 origin source coordinate。书本选择、documentRoot、source set、projection output、新鲜度判断和错误语义分属不同对象。
该链条的主要风险是 stale projection。TTL 仍然可能是合法 Turtle,查询引擎仍然可以返回结果,但这些结果对应不同的 source set。项目模式下,stale projection 不能作为当前书稿查询依据。
inkrail 介入的问题世界是本地书稿查询闭环。它不改变 AsciiDoc 源书稿,不替代 HTML 发布,不解释 payload 内部业务语义,也不改变 RDF 投影中的 origin source coordinate。
4. 设计坐标
本书使用需求工程中的关系式描述 inkrail 的判断结构:
Domain ∧ Specification ⊨ Requirements
Domain 是当前书稿世界中的事实。它包括标准多书书架结构、书架本地构建运行时、book entry、documentRoot、source set、RDF12 投影、Oxigraph 本地查询能力、单本书查询边界和 origin source coordinate。
Requirements 是作者希望达到的状态。作者需要用较少路径记忆和较少刷新心智负担,对当前书稿事实发起结构查询,并得到带 source coordinate、可审计、可重复的结果。
项目模式查询的目标是代表当前 book-entry source set 的 RDF12 TTL。
Specification 是 inkrail 能直接控制的规约。它包括项目配置、书本选择、标准 profile 路径推导、书架本地构建调度、source set 新鲜度、投影刷新状态机、SPARQL 查询执行、pretty 输出、JSON 输出和错误语义。
inkrail 不能直接改变源书稿世界。它只能通过可控规约把当前书稿事实投影为可查询对象,并阻止过期投影进入当前查询。
项目记忆对应 bounded rationality 的工程处理。作者不应在每次查询时重新记忆书架根、book id、book entry、documentRoot、TTL 路径和刷新条件。inkrail 用 .inkrail/config.toml 与 .inkrail/state/ 把这些状态外化为可检查对象。
投影概念用于区分对象和表面。TTL、JSON-LD、pretty 表格、JSON envelope 都是投影。投影服务不同消费者,但投影不能替代人工制品本体。inkrail 的本体是书架、书本、source set、projection state 和查询契约之间的受控关系。
无项目模式服务临时实验。query --ttl 和 project <file.adoc> 不读取项目配置,不写项目状态,也不扩大项目模式的公共契约。无项目模式不判断项目新鲜度,也不声称给定 TTL 代表某个当前书稿。
5. 对象边界
inkrail 不实现 AsciiDoc parser。AsciiDoc 语义由 Asciidoctor 和 asciidoc-abundant-tree 承担。inkrail 只协调项目记忆、投影产物和查询执行。
inkrail 不实现 include resolver。Book-entry parsing、origin coordinate recovery、tree 输出、JSON 输出、RDF12 投影和 RDF12 JSON-LD 投影的语义来源是 asciidoc-abundant-tree。
inkrail 项目模式一次查询一本书。跨书联合图不属于当前公共契约。跨书联合查询会引入 label 空间、IRI 命名、source provenance、跨书 xref 绑定和结果归属问题;这些问题没有进入当前需求边界。
inkrail 查询命令消费 RDF 投影中的 source coordinate。查询结果提供 path、headingLine、start、end、raw、selector、headline 等字段;这些字段的坐标语义由 RDF 投影契约承担。
inkrail 不解释 payload raw。payload 的 JSON、YAML、TOML、XML 或其它格式作为 raw 文本保留。inkrail 可以查询 payload 绑定事实,但不把 payload 展开为业务图。
inkrail 不判断写作质量。未绑定 xref、多义 xref、重复 headline、重复 address label 和 degree 统计都是结构事实。它们提供作者判断入口,不自动构成错误结论。
inkrail 不把 stale projection 作为当前书稿事实。项目模式下,过期 TTL 不可查询。source set 构造或投影失败时,查询失败。
inkrail 不实现标准书架的 HTML 构建运行时。标准书架的 build、check 和 clean 动作由书架本地运行时承担。inkrail 可以调度这些动作,但不把 HTML 构建作为项目查询前置条件。
inkrail 不在每次命令结果中输出 source coordinate 教学文本。README 和指南说明 source coordinate、documentRoot 和编辑动作之间的关系。
第二部:书架与项目记忆
本部定义 inkrail 如何识别标准书架、记录项目记忆、推导书本路径、创建书架并调度书架本地构建检查动作。标准 profile 负责标准多书工作区,custom profile 负责非标准书架。
6. 标准书架模板
inkrail 集成的标准书架由 create-asciidoc-multi-book-workspace 默认模板创建。该模板创建 user-owned、book-first 的 AsciiDoc 多书工作区。
标准书架根目录包含:
README.md
catalog.adoc
package.json
.gitignore
tools/adoc-books.mjs
books/
shared/
每本书位于 books/<book-id>/,并以 book.adoc 作为唯一入口。catalog.adoc 是书架网页入口和书目导航。shared/ 保存跨书共享属性和共享图片。单书图片保留在 books/<book-id>/assets/images/。单书示例代码保留在对应书内。
tools/adoc-books.mjs 是标准书架本地运行时。该脚本属于生成工作区,负责书架 HTML 构建、展开后 ADOC 输出、资源复制和工作区合同检查。
标准书架提供以下本地 package scripts:
pnpm run build
pnpm run check
pnpm run clean
build 生成 HTML、展开后 ADOC、复制资源、写根 index.html,并运行当前工作区合同检查。HTML 发布不是 inkrail query 的前置条件。
check 执行与构建同源的当前工作区检查。该检查验证当前 catalog.adoc、现存 book、:doctype: book、跨书 xref、anchor 和本地 HTML 资源。
clean 删除书架构建生成物。
标准书架默认包含七本样本书。样本书是学习材料和复制起点,可以从用户工作区删除。inkrail 不把样本书自动登记为项目记忆中的查询目标。
生成工作区不包含维护者源码、维护者测试、发布配置或维护者设计文档。
inkrail 的标准 profile 路径推导只依赖生成工作区的可复用契约:catalog.adoc、books/<book-id>/book.adoc、shared/、包元数据和 book-first 目录结构。书架本地构建调度依赖本地 package scripts 和 tools/adoc-books.mjs。
7. 项目配置模型
项目记忆由 .inkrail/config.toml 表达。项目根通过显式 --project <path> 或从当前目录向上查找 .inkrail/config.toml 解析。
标准书架的最小配置如下:
[project]
default_book = "10-inkrail-cli-design"
[[bookshelves]]
id = "docs"
root = "docs/bookshelf"
profile = "inkrail-asciidoc-multi-book"
[[books]]
id = "10-inkrail-cli-design"
bookshelf = "docs"
project.default_book 指定项目模式下未传 --book 时使用的书本。项目存在多本书且没有 default_book 时,查询命令必须要求用户指定 --book。
bookshelves.id 是书架标识。该标识必须是 CLI identifier。bookshelves.root 是相对项目根的 POSIX 路径,不允许绝对路径、反斜杠和 .. 路径穿越。
bookshelves.profile 决定路径推导规则。inkrail-asciidoc-multi-book 是标准书架 profile。custom 是非标准书架 profile。
books.id 是 books/<book-id>/ 的目录名。标准 profile 下,bookshelf 与 id 唯一决定 book entry、documentRoot、RDF12 TTL、RDF12 JSON-LD、标准书架构建产物位置和 watch globs。
标准 profile 的 book 配置不得声明 book_entry、document_root、rdf12_ttl、rdf12_jsonld 或 watch。这些字段由 profile 规则推导。手写同名字段会制造两个路径来源,应作为 BOOK_CONFIG_INVALID 处理。HTML 和展开后 ADOC 是标准书架本地构建产物路径,不作为 book 配置字段声明。
custom profile 必须完整声明查询路径和 watch:
[[bookshelves]]
id = "custom-docs"
root = "docs"
profile = "custom"
[[books]]
id = "manual"
bookshelf = "custom-docs"
book_entry = "books/manual/book.adoc"
document_root = "."
rdf12_ttl = "build/rdf12/books/manual.ttl"
rdf12_jsonld = "build/rdf12/books/manual.jsonld"
watch = ["books/manual/**/*.adoc", "shared/**/*.adoc"]
标准 profile 避免用户重复声明模板已经确定的路径。custom profile 避免 inkrail 对非标准书架作无根据推断。两者之间不存在半自动配置层。
8. 书本对象推导
标准 profile 下,bookshelf.root 与 books.id 推导目标书的输入、投影输出、发布输出和 watch globs。
| 对象 | 推导值 |
|---|---|
Book entry |
|
DocumentRoot |
bookshelf root |
RDF12 TTL |
|
RDF12 JSON-LD |
|
HTML |
|
展开后 ADOC |
|
所有路径都相对 bookshelf.root 解释。inkrail 对外展示时可以显示相对项目根路径,但状态判断必须以物化后的绝对路径执行文件操作。
标准 profile 的 watch globs 是:
books/<book-id>/**/*.adoc
shared/**/*.adoc
Watch globs 服务快速变化检测。Source set fingerprint 由 book-entry include graph 到达的 source files 构成;投影器版本和 projection options 进入 projection fingerprint。
展开后 ADOC 和 HTML 是标准书架本地构建产物。它们不参与 inkrail query 的 RDF12 TTL 新鲜度判断。
rdf12_jsonld 是配置字段名。命令行 format 使用 rdf12-json-ld,文件后缀使用 .jsonld。
9. 初始化契约
inkrail init 初始化项目记忆。该命令在目标项目下创建:
.inkrail/config.toml
.inkrail/cache/
.inkrail/state/
该命令不创建 AsciiDoc 书架。它只建立 inkrail 项目上下文。
inkrail bookshelf init <target-dir> 从 标准书架模板 创建多书书架。目标目录不存在时创建。目标目录存在且为空目录时使用。目标路径存在且不是目录时,命令失败。目标目录非空且未传 --force 时,命令失败。
书架初始化命令支持:
inkrail bookshelf init docs/bookshelf
inkrail bookshelf init docs/bookshelf --force
--force 覆盖标准模板固定输出路径,并保留目标目录中的未知用户文件。固定输出路径包括 README.md、catalog.adoc、package.json、.gitignore、tools/adoc-books.mjs、books/ 和 shared/。
inkrail bookshelves add 把已有书架登记到项目记忆:
inkrail bookshelves add docs --root docs/bookshelf --profile inkrail-asciidoc-multi-book
inkrail books add 把一本书登记到项目记忆:
inkrail books add 10-inkrail-cli-design --bookshelf docs
inkrail books use 设置项目默认书:
inkrail books use 10-inkrail-cli-design
bookshelf init 可以提供注册选项:
inkrail bookshelf init docs/bookshelf --register docs
bookshelf init 不登记模板样本书。需要查询某本书时,调用者必须显式执行 inkrail books add。
从空项目到项目模式查询目标的入口序列是:
inkrail init
inkrail bookshelf init docs/bookshelf --register docs
inkrail books add 10-inkrail-cli-design --bookshelf docs
inkrail books use 10-inkrail-cli-design
--force 只覆盖固定模板输出路径。未知用户文件不属于固定模板输出路径,初始化命令不得删除这些文件。
10. 书架本地构建调度
标准书架 提供 build、check 和 clean 三个本地 package script。inkrail 按项目记忆中的书架登记项调度这些动作。
inkrail bookshelf build docs
inkrail bookshelf check docs
inkrail bookshelf clean docs
inkrail bookshelf build <bookshelf-id> 在目标书架根目录执行标准书架本地 build script。该动作生成 HTML、展开后 ADOC 和书架构建检查所需的生成物。
inkrail bookshelf check <bookshelf-id> 在目标书架根目录执行标准书架本地 check script。该动作验证当前书架的 catalog、现存 book、xref、anchor 和本地资源,并允许书架本地运行时重建检查所需的生成物。
inkrail bookshelf clean <bookshelf-id> 在目标书架根目录执行标准书架本地 clean script。该动作删除书架本地构建生成物。
书架本地构建调度使用已登记书架的 bookshelves.root 作为工作目录。构建调度转发本地 script 的 stdout、stderr 和退出状态。非零退出状态映射为 BOOKSHELF_BUILD_FAILED。
书架本地构建调度不写 .inkrail/state/。RDF12 TTL 和 RDF12 JSON-LD 的投影状态由 刷新状态机 维护。
inkrail query 在项目模式下隐式执行刷新状态机,不隐式执行书架本地 build、check 或 clean script。HTML 构建、展开后 ADOC 输出和工作区合同检查不作为 RDF 查询前置条件。
目标书架未登记时,构建调度失败。目标书架不是标准 profile 时,构建调度失败。标准书架缺少本地 package script 时,构建调度失败。标准书架缺少 tools/adoc-books.mjs 时,构建调度失败。
第三部:投影与新鲜度
本部定义 RDF12 TTL、RDF12 JSON-LD、source set 指纹、projection 指纹和刷新状态机。项目模式查询只有在 RDF12 TTL 代表当前 book-entry source set 时才成立。
11. 投影生成物
RDF12 TTL 是 asciidoc-abundant-tree 的 rdf12 Turtle 输出。标准 profile 下,它位于:
build/rdf12/books/<book-id>.ttl
RDF12 TTL 是项目模式查询的输入。Oxigraph 加载该文件并执行 SPARQL。
RDF12 JSON-LD 是 asciidoc-abundant-tree 的 rdf12-json-ld 输出。标准 profile 下,它位于:
build/rdf12/books/<book-id>.jsonld
TTL 与 JSON-LD 的生成纪律来自 RDF 投影查询工作流的投影输入与生成物章节。
HTML 是发布表面。标准 profile 下,它位于:
build/html/books/<book-id>/book.html
展开后 ADOC 是标准书架本地构建表面。标准 profile 下,它位于:
build/adoc/books/<book-id>.adoc
TTL、JSON-LD、HTML 和展开后 ADOC 都是生成物。它们可以删除并重新生成。它们不作为手写源文件维护。
HTML 构建和展开后 ADOC 构建不参与 inkrail query 的新鲜度判断。查询前刷新只要求 RDF12 TTL 代表当前 book entry source set。
12. 指纹模型
inkrail 使用指纹判断投影生成物是否代表当前输入。
Source set fingerprint 描述 book-entry projection 实际到达的 source files。每个 source file 记录 relativePath、size、mtimeMs 和 content hash。mtimeMs 是快速变化线索,content hash 是内容事实。
Projection fingerprint 描述一个投影生成物。它记录投影格式、输出路径、输出 hash、projectedFromSourceSetHash、documentRoot、projector identity 和 projection options。
项目状态存储在:
.inkrail/state/
状态文件保存上次成功判断的 source set fingerprint 和 projection fingerprint。状态文件不替代产物本身。TTL 缺失时,即使状态声称存在投影,查询仍必须刷新。
RDF12 TTL 的 freshness 条件是:
-
目标书 book entry 存在。
-
当前 source set 可以构造。
-
RDF12 TTL 文件存在。
-
当前 source set hash 等于 TTL 状态中的
projectedFromSourceSetHash。 -
当前 documentRoot 等于 TTL 状态中的 documentRoot。
-
当前 projection options 与 TTL 状态中的 projection options 一致。
-
当前 projector identity 与 TTL 状态中的 projector identity 一致。
RDF12 JSON-LD 有独立 projection fingerprint。它可以与 TTL 基于同一个 source set hash 生成,但它不是 Oxigraph 查询输入。
13. 刷新状态机
项目模式查询前必须执行刷新状态机。
-
解析项目上下文。
-
解析唯一目标书。
-
根据 profile 物化 book entry、documentRoot、projection output 和 watch globs。
-
构造 book-entry source set。
-
计算 source set fingerprint。
-
当 RDF12 TTL 缺失时,生成 RDF12 TTL。
-
当 RDF12 TTL 的
projectedFromSourceSetHash与当前 source set hash 不一致时,生成 RDF12 TTL。 -
当 documentRoot、projection options 或 projector identity 与状态不一致时,生成 RDF12 TTL。
-
加载 RDF12 TTL 到 Oxigraph。
-
执行查询。
-
写入新的状态。
Book entry 不存在时,查询失败。Source set 构造失败时,查询失败。投影失败时,查询失败。TTL 加载失败时,查询失败。
项目模式不存在过期投影继续查询分支。inkrail 已经知道 TTL 不代表当前书稿事实时,不得使用该 TTL 回答当前查询。
查询失败不回滚已经成功写入的投影生成物。查询错误属于 SPARQL 执行层;已经完成的新鲜投影仍然可以保留。
inkrail refresh 主动执行同一状态机,但不执行用户查询。inkrail query 在项目模式下隐式执行该状态机。
14. RDF12 与 JSON-LD 投影
rdf12 是面向查询执行器的 Turtle 投影。项目模式查询依赖 RDF12 TTL。
rdf12-json-ld 是面向结构化消费者的 JSON-LD 投影。它不作为 Oxigraph 查询输入。
显式投影命令必须支持两个格式:
inkrail project path/to/file.adoc --format rdf12 --out path/to/file.adoc.ttl
inkrail project path/to/file.adoc --format rdf12-json-ld --out path/to/file.adoc.jsonld
显式投影命令默认使用 single-file input semantics。调用者可以选择 book-entry input semantics:
mkdir -p build/rdf12/books
inkrail project books/manual/book.adoc \
--mode book-entry \
--document-root docs/bookshelf \
--format rdf12 \
--out build/rdf12/books/manual.ttl
显式投影命令不写 .inkrail/state/。它只读取输入 adoc,生成指定输出文件。
项目刷新可以指定投影格式:
inkrail refresh --projection rdf12
inkrail refresh --projection rdf12-json-ld
inkrail refresh --projection all
项目模式 projection 输入是目标 book entry 和 documentRoot。query 只要求 rdf12 新鲜。refresh --projection all 生成 TTL 与 JSON-LD,并为两个投影分别记录 projection fingerprint。
第四部:查询契约
本部定义 inkrail 的查询执行器、查询模式、输出表面和错误语义。查询契约的核心是不污染结果表面,并保持 RDF term 的机器可解释性。
15. 查询执行器
inkrail 使用 Oxigraph 作为内置本地查询执行器。
Oxigraph 是 Rust 实现的 RDF store 和 SPARQL engine。JavaScript binding 通过 WebAssembly 暴露内存 store。inkrail 在本地读取 RDF12 TTL,把 Turtle 加载进 Oxigraph store,并在该 store 上执行 SPARQL。
该选择回应当前问题世界。inkrail 查询的是本地单本书 TTL,不是远程 RDF source federation。Oxigraph 的内存 store、轻依赖和直接 load/query 模型适合该场景。
inkrail 依赖的查询能力包括:
-
加载 Turtle。
-
执行 SELECT 查询。
-
执行 ASK 查询。
-
执行 CONSTRUCT 和 DESCRIBE 查询。
-
执行 property path。
-
返回
rdf:reifies指向的 triple term。
RDF 1.2 / RDF-star 相关能力必须通过 fixture 测试锁定。inkrail 不把 Oxigraph 的全部标准覆盖范围写成自身公共承诺。
查询语句使用 SPARQL。inkrail 不定义新的查询 DSL。内置命令是 SPARQL 模板的命令化表面,raw query 始终保留。
16. 查询模式
inkrail 有三种运行模式。
16.1. Project mode
Project mode 通过 .inkrail/config.toml 解析项目、书架和书本。
inkrail query --book 10-inkrail-cli-design --file query.sparql
inkrail xrefs unbound --book 10-inkrail-cli-design
Project mode 在查询前执行 刷新状态机。只有 RDF12 TTL 新鲜时,查询才执行。
Project mode 的 raw query 输入表面包括命令参数、查询文件和 stdin:
inkrail query 'SELECT ... WHERE { ... }'
inkrail query --file query.sparql
inkrail query --stdin < query.sparql
16.2. TTL-only mode
TTL-only mode 直接查询用户提供的 Turtle 文件。
inkrail query --ttl path/to/book.ttl --file query.sparql
TTL-only mode 不查找 .inkrail/config.toml,不计算 source set fingerprint,不刷新 projection,不判断 project freshness。该模式只声明给定 TTL 已被加载并查询。
TTL-only mode 接受与 Project mode 相同的 raw query 输入表面。
16.3. Explicit projection mode
Explicit projection mode 读取调用者指定的 adoc 文件并生成指定 RDF 投影。
inkrail project path/to/file.adoc --format rdf12 --out path/to/file.adoc.ttl
inkrail project path/to/file.adoc --format rdf12-json-ld --out path/to/file.adoc.jsonld
该模式默认使用 single-file 输入语义。调用者可以显式选择 book-entry 输入语义:
mkdir -p build/rdf12/books
inkrail project books/manual/book.adoc \
--mode book-entry \
--document-root docs/bookshelf \
--format rdf12 \
--out build/rdf12/books/manual.ttl
该模式不写项目状态。它服务临时实验、单文件分析和显式 book-entry 投影。
16.4. Book selection
Project mode 按以下顺序解析目标书:
-
命令行
--book <book-id>。 -
project.default_book。 -
项目只登记一本书时的唯一书。
项目登记多本书且没有命令行 --book 或 default_book 时,命令失败并返回 BOOK_REQUIRED。
17. 输出表面
inkrail 只有两类查询输出表面:pretty 和 JSON。
Pretty 是终端读者表面。它使用表格式输出,字段名直接使用 SPARQL 变量名。
sourceHeadline selector targetHeadline path start col raw
Pretty 输出写入 stdout。刷新事件、诊断和错误写入 stderr。stdout 不混入教学文本或进度事件。
ASK 查询的 pretty 输出使用单列表格,列名为 ask,值为 true 或 false。
CONSTRUCT 和 DESCRIBE 查询的 pretty 输出使用 RDF 三元组或四元组文本表面。该表面仍然写入 stdout;刷新事件和诊断仍然写入 stderr。
JSON 是机器、脚本和大语言模型表面。JSON 输出使用 envelope,保留模式、书本、投影、查询种类、变量名和 rows。
{
"ok": true,
"data": {
"mode": "project",
"book": {
"id": "10-inkrail-cli-design",
"bookshelf": "docs"
},
"projection": {
"format": "rdf12",
"path": "docs/bookshelf/build/rdf12/books/10-inkrail-cli-design.ttl",
"freshness": "fresh"
},
"query": {
"kind": "select",
"variables": ["sourceHeadline", "selector", "targetHeadline"]
},
"rows": []
}
}
JSON row value 必须保留 RDF term 结构。Literal 示例:
{
"termType": "Literal",
"value": "工作流对象",
"datatype": "http://www.w3.org/2001/XMLSchema#string",
"language": ""
}
NamedNode 示例:
{
"termType": "NamedNode",
"value": "urn:aat:doc:example#heading-l17-o0"
}
Triple term 或 quad term 必须结构化表示,不能只输出字符串。rdf:reifies ?relation 查询会返回 triple term;该对象结构属于机器输出契约。
SELECT 查询的 JSON query.kind 为 select,并使用 variables 与 rows 表达结果。ASK 查询的 query.kind 为 ask,并使用 value 表达布尔结果。CONSTRUCT 和 DESCRIBE 查询的 query.kind 分别为 construct 和 describe,并使用 quads 表达 RDF term 结构。
inkrail 输出契约只包含 pretty 和 JSON。其它导出表面需要消费者动作、字段规则和验证方式。
18. 错误语义
错误码是恢复动作的索引。inkrail 使用稳定错误码区分配置、书架、book entry、投影、加载和查询失败。
| 错误码 | 含义 | 恢复动作 |
|---|---|---|
|
项目无法解析唯一目标书。 |
传入 |
|
指定 book 未登记或标准书架中不存在对应 |
|
|
book 配置路径、profile 或字段不合法。 |
修正 |
|
书架根目录不存在。 |
检查 |
|
书架初始化目标路径存在且不是目录。 |
选择不存在路径或空目录作为目标书架目录。 |
|
书架初始化目标目录非空且未传 |
选择空目录,或传入 |
|
指定书架未登记。 |
|
|
书架本地构建调度收到非标准 profile。 |
使用标准 profile 书架,或直接在目标书架内运行自有构建命令。 |
|
标准书架缺少本地 |
检查书架 |
|
标准书架缺少 |
检查标准书架初始化结果。 |
|
标准书架本地 |
阅读书架本地运行时输出并修复书架源文件或构建环境。 |
|
书本入口不存在。 |
创建或修正 |
|
book-entry source set 无法构造。 |
检查 include target、include attrlist、documentRoot 和 include path 边界。 |
|
book entry 到 RDF 投影失败。 |
检查 book entry、投影器版本和 projection options。 |
|
TTL 文件无法读取。 |
检查文件权限和路径。 |
|
Oxigraph 无法加载 TTL。 |
重新投影或检查 Turtle 语法。 |
|
查询文本无法读取。 |
检查 |
|
SPARQL 执行失败。 |
修正查询语句或查询能力假设。 |
|
项目模式检测到过期投影且无法刷新。 |
修复 source set 或投影失败原因;不能使用 stale TTL 继续查询。 |
|
外部命令缺失。 |
安装依赖或修正配置命令。 |
成功 JSON 写 stdout。失败 JSON 写 stderr。pretty 模式失败时,stderr 输出错误码、错误消息和必要 details,不输出 stack trace。
第五部:内置查询动作
本部把既有 RDF 投影查询工作流中的作者动作映射为 inkrail 内置命令。内置命令不发明新查询;它们是工作流指南查询语句的命令化表面。
19. 查询模板契约
每个内置查询命令都接受 --print-query。该选项把命令对应的 SPARQL 写入 stdout,不执行查询,不读取 TTL,也不触发刷新状态机。
内置查询模板必须保持 查询工作流指南 的查询语义。SELECT 变量、排序字段、property path、OPTIONAL、FILTER NOT EXISTS、GROUP BY 和 HAVING 条件属于查询契约。命令参数只能替换指南查询中的占位 literal 或 scope label,不能改变查询动作的事实边界。
20. 来源确认动作
来源确认动作验证当前 TTL 来自哪个 book entry。
inkrail source
输出变量:
path digest
path 是 RDF 投影中的 aat:relativePath。digest 是投影记录的 source digest。该动作应在跨项目查询和异常结果审查时使用。
--print-query 输出来源确认 SPARQL,不执行查询。
21. 标题动作
标题动作来自 查询工作流指南的标题定位与切片查询。
目录骨架:
inkrail outline
inkrail outline --levels 2
输出变量:
level headline path headingLine
按 address label 定位:
inkrail heading locate --label <label>
输出变量:
heading headline path headingLine start end
按 headline 定位:
inkrail heading locate --headline <headline>
输出变量:
heading headline path headingLine start end label generated
headline 可以重复。该命令保留多行结果,不自动选择第一行。
读取标题自身 raw:
inkrail heading raw --label <label>
输出变量:
headline path start end raw
label 空间检查:
inkrail labels
输出变量:
heading headline path label generated headingLine
标题定位动作按 path 和 headingLine 排序。标题 raw 动作使用 start 和 end 返回 heading slice。排序是查询契约的一部分。
22. 结构范围动作
结构范围动作来自 查询工作流指南的结构范围查询。它读取 heading 之间的父子和兄弟关系。
直接子标题:
inkrail structure children --label <label>
输出变量:
child childHeadline path childLine start end
递归后代:
inkrail structure descendants --label <label>
输出变量:
descendant level headline path headingLine start end
包含根节点的子树:
inkrail structure subtree --label <label>
输出变量:
node level headline path headingLine start end
父标题反查:
inkrail structure parent --label <label>
输出变量:
parent parentHeadline parentPath parentLine parentSliceStart parentSliceEnd
前一个同父兄弟:
inkrail structure previous-sibling --label <label>
输出变量:
headingHeadline previousHeadline path headingLine
结构范围动作按 path、heading line 或指南指定字段排序。结构范围提供阅读边界,不替代 xref 脉络。
23. 交叉引用动作
交叉引用动作来自 查询工作流指南的交叉引用边查询。它们读取 aat:XrefEdge 边证据。
发出的交叉引用:
inkrail xrefs outgoing --label <label>
输出变量:
edge selector target targetHeadline raw path start col
指向当前标题的交叉引用:
inkrail xrefs incoming --label <label>
输出变量:
source sourceHeadline raw path start col
全书交叉引用表:
inkrail xrefs list
输出变量:
sourceHeadline selector targetHeadline path start col raw
未绑定交叉引用:
inkrail xrefs unbound
输出变量:
sourceHeadline selector raw path start col
多义交叉引用:
inkrail xrefs ambiguous
输出变量:
sourceHeadline selector candidateHeadline candidatePath candidateLine raw path start
子树内部引用:
inkrail xrefs internal --label <label>
输出变量:
sourceHeadline targetHeadline path start
未绑定和多义结果是结构事实,不自动构成错误结论。
24. Degree 与邻域动作
Degree 动作来自 查询工作流指南的引用入度与出度查询。它们统计 heading 在 xref 网络中的连接数量。
出度:
inkrail degree out
输出变量:
heading headline outDegree
入度:
inkrail degree in
输出变量:
heading headline inDegree
合并入度与出度:
inkrail degree both
输出变量:
heading headline inDegree outDegree
范围内出度:
inkrail degree out --scope <label>
输出变量:
heading headline outDegree
范围外依赖数量:
inkrail degree external-out --scope <label>
输出变量:
source sourceHeadline externalOutDegree
邻域动作来自 查询工作流指南的交叉引用邻域查询。它们读取一个 heading 周围的局部 xref 网络。
inkrail neighborhood out --label <label> --depth 1
inkrail neighborhood in --label <label> --depth 1
inkrail neighborhood out --label <label> --depth 2
inkrail neighborhood in --label <label> --depth 2
inkrail neighborhood both --label <label>
inkrail neighborhood external-out --scope <label>
inkrail neighborhood external-in --scope <label>
邻域命令的输出变量沿用工作流指南中的 target、targetHeadline、targetPath、targetLine、source、sourceHeadline、sourcePath、sourceLine、near、nearHeadline、nearPath、nearLine、far、farHeadline、farPath、farLine、direction、neighbor、neighborHeadline、edgePath、edgeStart、path、start 和 raw。
Degree 高低是阅读和审计信号,不是内容质量判决。
25. 审计动作
审计动作来自 查询工作流指南的质量审计查询。它们暴露书稿结构事实。审计结果提供作者判断入口,不自动给出内容评价。
重复 address label:
inkrail audit duplicate-labels
输出变量:
label count
重复 headline:
inkrail audit duplicate-headlines
输出变量:
headline count
节点 payload:
inkrail audit payloads --kind node
输出变量:
headingHeadline payloadId format payloadPath payloadStart payloadEnd
边 payload:
inkrail audit payloads --kind edge
输出变量:
sourceHeadline targetHeadline payloadId format payloadPath payloadStart payloadEnd
raw 抽查:
inkrail audit raw --headline <headline> --contains <fragment>
输出变量:
headline path headingLine containsExpected
containsExpected 是查询结果,不是测试断言。需要把它作为自动化回归条件时,应由调用方检查 JSON 输出。
第六部:验证与文档
本部定义 inkrail 的验证合同和文档职责。验证合同说明哪些对象必须被测试锁定;文档职责说明哪些解释属于 README 或指南,而不是命令输出。
26. 测试合同
inkrail 的测试必须覆盖对象契约,而不是只证明命令可运行。
配置测试必须覆盖:
-
非法 book id。
-
重复 bookshelf id。
-
重复 book id。
-
路径为绝对路径。
-
路径包含反斜杠。
-
路径包含
..。 -
default_book指向未登记 book。 -
standard profile 禁止手写冲突路径。
-
custom profile 缺少必填路径。
书本选择测试必须覆盖:
-
--book优先于default_book。 -
default_book生效。 -
单 book 项目可解析唯一书。
-
多 book 项目无目标书时报
BOOK_REQUIRED。 -
指定未知 book 时报
BOOK_NOT_FOUND。
路径推导测试必须覆盖 standard profile 下的 book_entry、document_root、rdf12_ttl、rdf12_jsonld、html、展开后 ADOC 和 watch globs。
新鲜度测试必须覆盖:
-
book entry 缺失时查询失败。
-
book-entry source set 构造失败时查询失败。
-
source set fingerprint 变化触发 RDF12 重投影。
-
source set hash 不变时不重投影 RDF12。
-
RDF12 TTL 缺失触发投影。
-
RDF12 TTL 的
projectedFromSourceSetHash不匹配触发投影。 -
documentRoot、projection options 或 projector identity 不匹配触发投影。
-
shared attributes 参与 source set fingerprint。
-
投影失败时查询失败。
-
不存在过期投影继续查询分支。
Oxigraph 查询测试必须覆盖:
-
SELECT 查询。
-
ASK 查询。
-
CONSTRUCT 或 DESCRIBE 查询。
-
property path。
-
rdf:reifies ?relation返回 triple term。 -
Turtle 加载错误映射为
TTL_LOAD_FAILED。 -
SPARQL 错误映射为
QUERY_FAILED。
输出测试必须覆盖:
-
pretty 输出只在 stdout 写结果表。
-
刷新事件写 stderr。
-
JSON 输出保留 envelope。
-
JSON row value 保留 RDF term 结构。
-
triple term 不被压成普通字符串。
-
字段名沿用 SPARQL 变量名。
-
source coordinate 字段保留 origin source file 路径、heading line、line span、column span 和 raw。
内置查询测试必须覆盖:
-
每个内置命令生成的 SPARQL 与工作流指南语义一致。
-
每个内置命令的输出变量与 SELECT 变量一致。
-
--print-query输出 SPARQL,不执行查询。 -
查询排序与指南保持一致。
-
OPTIONAL、FILTER NOT EXISTS、GROUP BY、HAVING和 property path 语义不被模板封装改写。 -
内置查询返回的
path字段表示 origin source file。
RDF12 book-entry 投影测试必须覆盖:
-
项目模式使用 book-entry 输入语义。
-
RDF12 TTL 包含 source file reconstruction surface。
-
heading 查询输出 heading line;xref edge 和 payload 查询输出 origin source coordinate。
-
explicit projection mode 的 single-file input semantics 不隐式展开 include。
模板初始化测试必须覆盖:
书架本地构建调度测试必须覆盖:
-
已登记标准书架可以执行
build、check和clean。 -
未登记书架执行构建调度时报错。
-
标准书架缺少本地 package script 时报
BOOKSHELF_SCRIPT_NOT_FOUND。 -
标准书架缺少
tools/adoc-books.mjs时报BOOKSHELF_RUNTIME_NOT_FOUND。 -
标准书架本地 script 非零退出时报
BOOKSHELF_BUILD_FAILED。 -
构建调度转发本地 script 的 stdout 和 stderr。
-
构建调度不写 RDF projection state。
-
项目模式查询不隐式执行书架本地构建动作。
27. README 与指南契约
README 说明 inkrail 的工具定位、安装入口、项目初始化、书架初始化、书架登记、book 登记、书架本地构建调度、基础查询命令、配置文件位置、source-aware 输出表面和对象边界。
README 不展开全部内置查询语句。完整查询动作由本设计书和用户指南维护。
用户指南承担 source coordinate 说明。查询结果中的 path、headingLine、start、end、col 和 raw 指向 RDF fact 的 origin source file surface。修改书稿时,作者使用这些字段进入 source file。
用户指南说明从 book entry 到 RDF12 TTL、从查询结果到 origin source file、从源文件修改到下一次项目模式查询刷新之间的关系。
Source coordinate 说明应链接 RDF 投影查询工作流的阅读与修改闭环。该链接提供 path、heading line、line span、column、raw、编辑动作和修改后刷新之间的完整关系。
Source coordinate 说明不进入每次命令输出。命令输出只提供查询结果字段、刷新事件和错误诊断。
用户指南还应说明:
-
项目模式会强制刷新过期投影。
-
书架本地
build、check和clean可以由已登记书架调度。 -
书架本地构建调度不写 RDF projection state。
-
TTL-only mode 不判断项目新鲜度。
-
explicit projection mode 不写项目状态。
-
book-entry projection 使用 documentRoot 解释
relativePath。 -
模板样本书不自动进入项目记忆。
-
未绑定 xref、多义 xref、重复 headline 和 degree 统计是结构事实,不自动等于错误。
-
pretty 输出给终端读者,JSON 输出给机器和大语言模型。
README 和指南不得承诺跨书联合查询、payload 业务解释、远程 federation 或 stale TTL fallback。
28. 实现准备条件
实现 inkrail 前,以下契约必须保持稳定:
-
人工制品定义。
-
standard profile 与 custom profile 的配置边界。
-
standard profile 路径推导规则。
-
初始化命令契约。
-
书架本地构建调度契约。
-
source set 和 projection fingerprint 模型。
-
项目查询刷新状态机。
-
stale projection 不可查询规则。
-
rdf12与rdf12-json-ld投影边界。 -
project mode、ttl-only mode 和 explicit projection mode。
-
pretty 与 JSON 两类输出表面。
-
RDF term JSON 结构化输出规则。
-
错误码和恢复动作。
-
内置查询动作集合。
-
README 与指南职责。
-
测试合同。
实现计划应从这些契约派生。实现计划可以安排文件顺序、测试顺序和提交顺序,但不得用实施阶段改写对象边界。
Appendix A: 命令表面
项目记忆:
inkrail init
inkrail status
inkrail config print
inkrail doctor
书架与书本:
inkrail bookshelf init <target-dir>
inkrail bookshelf init <target-dir> --force
inkrail bookshelf init <target-dir> --register <bookshelf-id>
inkrail bookshelf init <target-dir> --force --register <bookshelf-id>
inkrail bookshelves add <id> --root <path> --profile inkrail-asciidoc-multi-book
inkrail books add <book-id> --bookshelf <bookshelf-id>
inkrail books use <book-id>
inkrail books list
inkrail bookshelf build <bookshelf-id>
inkrail bookshelf check <bookshelf-id>
inkrail bookshelf clean <bookshelf-id>
刷新与投影:
inkrail refresh
inkrail refresh --book <book-id>
inkrail refresh --projection rdf12
inkrail refresh --projection rdf12-json-ld
inkrail refresh --projection all
inkrail project <file.adoc> --format rdf12 --out <file.adoc.ttl>
inkrail project <file.adoc> --format rdf12-json-ld --out <file.adoc.jsonld>
inkrail project <book.adoc> --mode book-entry --document-root <root> --format rdf12 --out <book.ttl>
Raw query:
inkrail query '<sparql>'
inkrail query --file query.sparql
inkrail query --stdin < query.sparql
inkrail query --ttl path/to/file.ttl --file query.sparql
inkrail query --json --file query.sparql
内置查询:
inkrail source
inkrail outline
inkrail heading locate --label <label>
inkrail heading locate --headline <headline>
inkrail heading raw --label <label>
inkrail labels
inkrail structure children --label <label>
inkrail structure descendants --label <label>
inkrail structure subtree --label <label>
inkrail structure parent --label <label>
inkrail structure previous-sibling --label <label>
inkrail xrefs outgoing --label <label>
inkrail xrefs incoming --label <label>
inkrail xrefs list
inkrail xrefs unbound
inkrail xrefs ambiguous
inkrail xrefs internal --label <label>
inkrail degree out
inkrail degree in
inkrail degree both
inkrail degree out --scope <label>
inkrail degree external-out --scope <label>
inkrail neighborhood out --label <label> --depth 1
inkrail neighborhood in --label <label> --depth 1
inkrail neighborhood out --label <label> --depth 2
inkrail neighborhood in --label <label> --depth 2
inkrail neighborhood both --label <label>
inkrail neighborhood external-out --scope <label>
inkrail neighborhood external-in --scope <label>
inkrail audit duplicate-labels
inkrail audit duplicate-headlines
inkrail audit payloads --kind node
inkrail audit payloads --kind edge
inkrail audit raw --headline <headline> --contains <fragment>
Appendix B: 配置示例
标准书架配置:
[project]
default_book = "10-inkrail-cli-design"
[[bookshelves]]
id = "docs"
root = "docs/bookshelf"
profile = "inkrail-asciidoc-multi-book"
[[books]]
id = "10-inkrail-cli-design"
bookshelf = "docs"
custom 书架配置:
[project]
default_book = "manual"
[[bookshelves]]
id = "custom-docs"
root = "docs"
profile = "custom"
[[books]]
id = "manual"
bookshelf = "custom-docs"
book_entry = "books/manual/book.adoc"
document_root = "."
rdf12_ttl = "build/rdf12/books/manual.ttl"
rdf12_jsonld = "build/rdf12/books/manual.jsonld"
watch = [
"books/manual/**/*.adoc",
"shared/**/*.adoc"
]
标准 profile 的推导路径:
book_entry books/<book-id>/book.adoc
document_root .
rdf12_ttl build/rdf12/books/<book-id>.ttl
rdf12_jsonld build/rdf12/books/<book-id>.jsonld
html output build/html/books/<book-id>/book.html
expanded ADOC build/adoc/books/<book-id>.adoc
Appendix C: 查询动作映射
| 工作流动作 | 命令 | 输出变量 |
|---|---|---|
来源确认 |
|
|
目录骨架 |
|
|
按 address label 定位 |
|
|
按 headline 定位 |
|
|
标题 raw |
|
|
label 空间 |
|
|
直接子标题 |
|
|
递归后代 |
|
|
包含根节点的子树 |
|
|
父标题反查 |
|
|
兄弟顺序 |
|
|
发出的 xref |
|
|
指向当前标题的 xref |
|
|
全书 xref |
|
|
未绑定 xref |
|
|
多义 xref |
|
|
子树内部引用 |
|
|
出度 |
|
|
入度 |
|
|
入度与出度 |
|
|
范围内出度 |
|
|
范围外依赖数量 |
|
|
正向一跳邻域 |
|
|
反向一跳邻域 |
|
|
正向两跳邻域 |
|
|
反向两跳邻域 |
|
|
双向一跳邻域 |
|
|
子树向外引用 |
|
|
外部指向子树 |
|
|
重复 address label |
|
|
重复 headline |
|
|
节点 payload |
|
|
边 payload |
|
|
raw 抽查 |
|
|
术语表
- book
-
具有独立 book entry、章节顺序和生成物的书籍单位。
- bookshelf
-
保存 catalog、books、shared、书架本地运行时、包元数据和生成物的多书工作区。
- bookshelf local runtime
-
标准书架中的
tools/adoc-books.mjs;该脚本承担书架本地build、check和clean动作。 - standard bookshelf profile
-
inkrail对标准 AsciiDoc 多书工作区的路径、构建和 watch 推导规则。 - custom profile
-
非标准书架配置方式;书本路径和 watch 必须完整声明。
- project memory
-
.inkrail/config.toml与.inkrail/state/中保存的书架、书本和投影状态。 - book entry
-
调用者显式传入的书稿入口 source file,标准书架中为
books/<book-id>/book.adoc。 - documentRoot
-
aat:relativePath的基准和 include path 的边界,标准书架中为 bookshelf root。 - source set
-
book entry 通过受支持 include directive 到达的 source files 集合。
- RDF12 TTL
-
asciidoc-abundant-tree的rdf12Turtle 投影。 - RDF12 JSON-LD
-
asciidoc-abundant-tree的rdf12-json-ld投影。 - fresh projection
-
投影的 source set fingerprint、documentRoot、projection options 和 projector identity 与当前输入一致。
- stale projection
-
source set、documentRoot、projection options 或 projector identity 已改变,但投影未更新;项目模式下不可查询。
- project mode
-
通过
.inkrail/config.toml解析书本并执行新鲜度检查的命令模式。 - TTL-only mode
-
直接查询用户提供 TTL,不判断项目新鲜度的命令模式。
- explicit projection mode
-
读取调用者指定输入并生成
rdf12或rdf12-json-ld的命令模式;该模式不写项目状态。 - single-file input semantics
-
explicit projection mode 的默认输入语义;投影器只读取调用者指定的单个 source file。
- origin source coordinate
-
RDF fact 在 source file 中的
relativePath、heading line、line span、column span 和 raw 表面。 - pretty output
-
面向终端读者的表格式输出。
- JSON output
-
面向机器、脚本和大语言模型的结构化 envelope 输出。
参考资料
-
[simon-artificial] Herbert A. Simon, The Sciences of the Artificial, 1969.
-
[zave-jackson] Pamela Zave and Michael Jackson, “Four Dark Corners of Requirements Engineering”, ACM Transactions on Software Engineering and Methodology, 1997.
-
[hevner-dsr] Alan R. Hevner, Salvatore T. March, Jinsoo Park, and Sudha Ram, “Design Science in Information Systems Research”, MIS Quarterly, 2004.
-
[asciidoc-multi-book-workspace] MichengLiang, asciidoc-multi-book-workspace, https://github.com/MichengLiang/asciidoc-multi-book-workspace
-
[asciidoc-abundant-tree] MichengLiang, asciidoc-abundant-tree, https://github.com/MichengLiang/asciidoc-abundant-tree
-
[rdf12-concepts] W3C, RDF 1.2 Concepts and Abstract Data Model, https://www.w3.org/TR/rdf12-concepts/
-
[rdf12-turtle] W3C, RDF 1.2 Turtle, https://www.w3.org/TR/rdf12-turtle/
-
[sparql12-query] W3C, SPARQL 1.2 Query Language, https://www.w3.org/TR/sparql12-query/
-
[asciidoctor-parts] Asciidoctor Docs, Book Parts, https://docs.asciidoctor.org/asciidoc/latest/sections/parts/
-
[asciidoctor-include] Asciidoctor Docs, Include Directive, https://docs.asciidoctor.org/asciidoc/latest/directives/include/
-
[asciidoctor-xref] Asciidoctor Docs, Document to Document Cross References, https://docs.asciidoctor.org/asciidoc/latest/macros/inter-document-xref/
-
[oxigraph] Oxigraph, https://oxigraph.org/