forked from bai/curriculum-project-hub
f1dce07789
Picture the whole framework, then pin the element-kind language layer. System platform layer — rebuild the semantics likec4 can't draw (ADR-0001..0004): - Prelude: opaque Identifiers carrier (ProjectId/RunId/SessionId/Principal) - System/Run: RunState + Terminal subset (set completeness left OPEN, no invented pending) - System/Lock: lock owner=run (typed), LockTable exclusivity, WellFormed invariant (a lock holder must be a non-terminal run — couples Lock and Run) - System/Permission: read<edit<manage role lattice, capability derivation, can_mono monotonicity theorem; force-release sits outside the lattice (admin-only) - System/Audit: intentionally thin (mostly plumbing, OPEN) Courseware product layer — split the single Lesson file into focused modules and fix doc tautology: Primitives / Element / Lesson / Render / Diagnostic, plus QuestionBank and Course skeletons (core relations OPEN, not invented). Diagnostic upgrades WarnsIgnored into a severity-tagged checker rule. Element schema + rich-content model (ADR-0006, ADR-0007): - docs/adr/0006: kind schema is declarative JSON Schema; field types are built-in scalars plus a `content` extension; a `content` value is typst source taken as module body; rich content must carry a VirtualPath (else click-to-jump and relative import break — verified against typst source); import boundary = within the engineering file + @package - docs/adr/0007: on-disk form is a real directory tree (agent/grep friendly); VirtualPath = real relative path; layout conventions deferred - spec/Courseware/RichContent: prose anchor for rich content (opaque VPath, RichContentRef); ElementData kept abstract — JSON/typst internals are implementation detail, not contract lake build green (18 jobs), no sorry, toolchain v4.31.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
2.7 KiB
Lean4
55 lines
2.7 KiB
Lean4
/-!
|
|
# Primitives —— Courseware 契约的留白基元
|
|
|
|
课程工程文件模型(ADR-0005)依赖一组基元:element kind 怎么标识、某 kind 的数据
|
|
schema 是什么、export target 怎么标识、渲染规则的载荷长什么样。
|
|
|
|
把它们收口成一个载体 `Primitives`,让 lesson 模型在其上参数化——契约因此能谈
|
|
element / lesson / 渲染**之间的关系**,而把每个基元的**内部表示**留给实现。注意:
|
|
"某基元的语义已 PINNED"与"其表示进 Lean"是两回事——schema 的**形态**已由 ADR-0006
|
|
钉死(声明式 JSON Schema + 富内容叶子 = typst content),但那是 JSON / typst 的内部
|
|
结构、属实现细节,**不入 Lean**;Lean 只锚定"数据符合 kind schema"这条关系,故这些
|
|
基元在此仍以抽象类型承载。富内容这一新概念的 prose 母本见 `Courseware.RichContent`。
|
|
-/
|
|
|
|
namespace Spec.Courseware
|
|
|
|
/--
|
|
Courseware 契约基元载体(关系 `PINNED`, ADR-0005;各基元表示留给实现, ADR-0006)。
|
|
-/
|
|
structure Primitives where
|
|
/--
|
|
element kind 的标识(`PINNED` 开放宇宙, ADR-0005;表示 `OPEN`)。
|
|
|
|
**刻意用抽象类型而非 `inductive`**:ADR-0005 决定 kind 是开放可扩展宇宙(stdlib
|
|
default + 第三方),封闭枚举会直接违背它。这与 `RunState` 的"未封闭"不同——此处
|
|
开放是**已决策的**。
|
|
-/
|
|
KindId : Type
|
|
/--
|
|
某 kind 的合法数据类型(`PINNED` 依赖关系, ADR-0005;schema 形态 `PINNED` ADR-0006,
|
|
表示仍抽象)。
|
|
|
|
以 kind 为索引:不同 kind 的合法数据类型不同。这正是 ADR-0005"kind 的最小契约
|
|
= 数据 schema"的载体——`ElementData k` 即"符合 `k` 之 schema 的数据"。
|
|
|
|
schema 的**形态**已由 ADR-0006 定:声明式 **JSON Schema**,字段类型 = 内置标量 +
|
|
一个 `content` 扩展类型;`content` 字段的值是一段 **typst 源**(canonical 存为带
|
|
虚拟路径的源,语义取其 module body)。但这些是 JSON / typst 的内部结构——**实现
|
|
细节,非分歧点**,不进 Lean。故 `ElementData` 在此**仍是抽象类型**:契约只承诺
|
|
"存在一个由 kind 决定的合法数据类型",不复刻 JSON Schema / typst Content 的形状。
|
|
-/
|
|
ElementData : KindId → Type
|
|
/-- export target 的标识(`PINNED` 角色, ADR-0005;表示 `OPEN`)。一个 target 是对 lesson 的一种投影(讲义/教案/PPT/平台 archive…)。 -/
|
|
TargetId : Type
|
|
/--
|
|
渲染规则的载荷(表示 `OPEN`, ADR-0005)。
|
|
|
|
"某 kind 在某 target 下如何呈现"那条规则的**内容**。typst 是渲染后端之一(`PINNED`,
|
|
ADR-0005)、不是定义语言;但渲染管线/规则载荷的具体表示仍 `OPEN`。契约只关心规则
|
|
**在不在**(见 `Render`),不碰它是什么。
|
|
-/
|
|
RenderRule : Type
|
|
|
|
end Spec.Courseware
|