forked from EduCraft/curriculum-project-hub
73e9d258d6
按新文风(简洁书面中文)重写 spec/ 全部 Lean doc 注释、spec/README, 并顺根 README。核心:讲清产品逻辑、去伪术语、去 ADR 黑话、DRY。 语言:砍钉死/留痕/实现侧/将就/脑补/刻意等伪术语;短句;不复述文件系统 能看到的东西;typst 考据移出 spec 指向 ADR。 内容取舍(动结构): - System 层大改:删 can_mono 形式化定理、Capability 9 项枚举与 requiredRole 映射、RunState 6 构造子;Audit.lean 删除并入 System 顶部。 Hub 未建的部分一律 prose 占位,只留 Lock 的 owner=run 与 WellFormed。 - 澄清两个"检查":产品 checker(LLM 判不了合法性,checker 真跑工具补这块) vs 开发时 spec↔impl 一致性检查(无自动闸门)。Oracle 重新定位为 "checker 得委托外部工具才能判的事实",不是"Lean 没写形式化"。 - spec/README 补取舍判据 checklist(自顶向下逐步细化、不在 Lean 里验证实现)。 - 根 README 去 DRY:删硬编码版本号、cache 路径细节;宪法第 3 条吸收 "人/coding assistant 核对"修正;第 5 条与 spec/README 判据去重。 保留:Export/Render 执行语义、Info 的 raw→canonical 设计模式(产品语义, 只顺文风不砍结构);renderIgnoredSeverity(实现对齐依赖)。 lake build 通过(24 jobs)。 Co-Authored-By: Claude <noreply@anthropic.com>
95 lines
5.6 KiB
Lean4
95 lines
5.6 KiB
Lean4
import Spec.Courseware.Model.Primitives
|
|
import Spec.Courseware.Export.Artifact
|
|
|
|
/-!
|
|
# Render —— export target = artifact + 有序 typed steps
|
|
|
|
一个 export target 是一次 build,产出一个有类型的 `Artifact`(ADR-0009)。build 的形状
|
|
是:一个 target = `artifact` + 一串有序的 typed step(ADR-0011)。
|
|
|
|
- `typstCompile template` —— 把模板文件(如 `exports/student.typ`)编译成产物。它是
|
|
typed 而非裸 shell,因为框架要把 manifest 注入模板(经 `--input manifest=…`),裸
|
|
字符串表达不了这个 wiring。presentation(编号、样式)住模板里,不在 manifest。
|
|
- `shell run` —— 逃生口,给难以声明的步骤。
|
|
- `assembleMarkdown field` —— 按 parts 顺序把每个 element 的 `field`(markdown content
|
|
叶子,ADR-0015)拼成单文件 markdown 产物。typed 而非裸 `cat`:按 manifest `[[parts]]`
|
|
顺序读取 + 跳过缺失项 + 写到单文件产物路径,框架自己来比裸 shell 稳。
|
|
|
|
渲染覆盖:契约只保留覆盖声明 `covers`(该 target 渲染哪些 kind),供种子诊断用;渲染的
|
|
"how"住模板里(ADR-0011)。
|
|
|
|
shell step 的执行语义(ADR-0013):`shell` 会被执行,语义是把 `run` 交给平台 shell、以
|
|
工程根为工作目录运行,产物由被调外部工具自己写出(框架不装配内容)。三条边界:
|
|
|
|
1. opt-in:命令执行只在用户显式 build 一个 shell target 时发生,绝不在 `check` 里跑。
|
|
`check` 只校验结构,不执行外部工具、不验其产物。
|
|
2. 失败归属:shell step 退出非零是一次 build 过程失败,不是 lesson 的合法性缺陷;因此
|
|
它不进 `Diagnostic` 的 7 类(那 7 类是 lesson 自身的诊断,见 `Check/Diagnostic.lean`),
|
|
而由 build 执行层报告。诊断分类保持 7 类不变。
|
|
3. 非-typst target 不过 typst 编译:一个只含 `shell` step 的 target(教具包即此)由
|
|
执行器跑命令,而非走 typst 引擎;`check` 的 compile 阶段跳过它。
|
|
|
|
assembleMarkdown step 的执行语义(ADR-0015):与 `shell` 同属"非-typst target"。框架
|
|
自己读每个 element 的 `<field>.md`、按 `[[parts]]` 顺序拼接、写到单文件产物路径(产物
|
|
是 markdown,不经 typst 引擎)。同 shell 的三条边界:① 只在显式 `build --target` 跑,
|
|
`check` 不跑;② 装配失败(如写盘失败、引用图缺失)是 build 过程错误,不入 7 类诊断;
|
|
③ 非-typst target,`check` 的 compile 阶段跳过它。
|
|
|
|
单文件产物(现):装配器注入课程级标题为文档 h1(课程元数据,非 element 内容),每份
|
|
`slides.md`/`transcript.md` 贡献其 `##` part 与 `###` 小节(presentation 在内容里,
|
|
ADR-0011),按 `[[parts]]` 顺序拼接(分隔符空行)。自包含:装配器扫描产物里的 ``
|
|
图引用,把引用到的本地图从工程根按原相对路径复制进产物所在 build 根,使该 build 目录
|
|
可独立交付;引用图在工程根缺失属 build 过程错误(不入 7 类)。外部 URL(`http(s)://`、
|
|
`data:`)不复制。结构化 FileTree 产物延后(待 parts 树形重组,ADR-0015 OPEN)。
|
|
-/
|
|
|
|
namespace Spec.Courseware
|
|
|
|
variable (P : Primitives)
|
|
|
|
/-- 一个 build step(ADR-0011;可扩展)。MVP 仅一个 `typstCompile`;`steps` 是 list 因为
|
|
FileTree、第三方 build 会需多步。不把模板内部、shell 命令的解析结构写进来(实现细节,
|
|
ADR-0011 OPEN)。 -/
|
|
inductive Step where
|
|
/-- 编译模板文件 `template`(相对工程根)成产物;框架注入 manifest。typed 的理由:
|
|
注入这件事裸 shell 写不出。 -/
|
|
| typstCompile (template : String)
|
|
/-- shell 逃生口:执行命令 `run`(ADR-0013)。以工程根为 cwd 执行,opt-in(只在显式
|
|
build 该 target 时跑,`check` 不跑),失败属 build 过程错误而非 lesson 诊断。
|
|
教具包(如 KenKen 交互 HTML 由外部 `kendoku` 生成)即走此 step。 -/
|
|
| shell (run : String)
|
|
/-- 装配 markdown:按 `[[parts]]` 顺序读取每个 element 的 `field`(markdown content 叶子,
|
|
ADR-0015),注入课程 h1 后拼接成单文件 markdown 产物,并收集 `` 引用的本地图
|
|
进 build 根使产物自包含。typed 而非 `cat`:按序读取+跳过缺失+注入标题+写盘+收集图由
|
|
框架自己来。非-typst target(`check` 不跑,失败属 build 过程错误不入 7 类诊断)。
|
|
slides 大纲、逐字稿口播即走此 step(直接 markdown+KaTeX 撰写,绕开 typst→md 公式转换,
|
|
ADR-0014)。 -/
|
|
| assembleMarkdown (field : String)
|
|
|
|
/-- 一个 export target 的 build 规格(ADR-0011:artifact + 有序 steps)。 -/
|
|
structure TargetSpec where
|
|
/-- 产物(带字段,ADR-0011)。决定 build 折叠成单文件还是文件树。 -/
|
|
artifact : Artifact
|
|
/-- 有序 build steps。按序执行;MVP 仅一个 `typstCompile`。 -/
|
|
steps : List Step
|
|
/-- 覆盖声明:`covers k` 表示此 target 渲染 kind `k`。契约只声明"渲染哪些 kind"
|
|
(种子诊断 `renderIgnored` 用),"how"由 `steps` 的模板实现(ADR-0011)。 -/
|
|
covers : P.KindId → Prop
|
|
|
|
/-- 渲染配置(ADR-0009/0011)。`spec t = none` 表示 target `t` 未声明(不导出);
|
|
`some s` 给出其 build 规格。 -/
|
|
structure RenderConfig where
|
|
/-- target ↦ 该 target 的 build 规格(未声明则 `none`)。 -/
|
|
spec : P.TargetId → Option (TargetSpec P)
|
|
|
|
/-- kind `k` 在 target `t` 下被渲染(ADR-0009/0011)。成立 ⟺ `t` 已声明
|
|
(`spec t = some s`)且 `s.covers k`。为假即"此 kind 在此 target 下不被渲染"——
|
|
checker 据此报 warning(见 `Diagnostic.renderIgnored`)。 -/
|
|
def RenderConfig.covers {P : Primitives} (c : RenderConfig P)
|
|
(k : P.KindId) (t : P.TargetId) : Prop :=
|
|
match c.spec t with
|
|
| none => False
|
|
| some s => s.covers k
|
|
|
|
end Spec.Courseware
|