Commit Graph

8 Commits

Author SHA1 Message Date
hongjr03 3f9b60f692 chore: remove Lean spec; ADRs are the single source of truth
The spec/ Lean semantic master had no conformance gate, no codegen, and
no CI tie to implementations — alignment was carried entirely by human
review, the same mechanism that carries the ADRs. In practice the ADRs
plus greppable code comments were already the load-bearing artifacts,
so spec/ was the most expensive kind of stale documentation.

- delete spec/ and the spec-check CI workflow
- README: constitution rewritten around ADRs as decision truth
- AGENTS.md/CLAUDE.md: discipline re-anchored (new decisions -> new ADR,
  never rewrite ADR history; supersede instead)
- code comments: re-anchor 'Mirrors Spec.X' invariants to ADR numbers
  (cph-diag, cph-check, cph-model, hub runner/capacity/org, prisma)
- leave ADR bodies and .scratch audit snapshots untouched (history);
  fix live references in open readiness tickets
2026-07-20 09:07:26 +00:00
hongjr03 5f791c5ce4 chore: restore checker CI gate 2026-07-10 13:46:22 +08:00
sjfhsjfh 144e2d8c80 feat(spec+checker): slides/逐字稿 markdown 内容面 + assembleMarkdown step(ADR-0015)
给课程加两个 markdown 内容面:slides(大纲:h2 part → h3 小节 → ![]() 图 +
:::widget 教具)与逐字稿(口播)。直接 markdown+KaTeX 撰写,绕开 typst→md
公式转换(等于在 slides 面选 ADR-0014 的 R2)。

spec:
- RichContent.lean: content leaf 带 format(typst|markdown),新增 ContentFormat
  归纳,RichContentRef 加 format 字段
- Export/Render.lean: Step 加 assembleMarkdown (field),钉执行语义
  (同 shell 三边界 + 注入课程 h1 + 自包含收集引用图)
- Courseware.lean: ADR 区间 →0015

实现:
- cph-schema: x-cph-content 支持 true→.typ / 字符串→该扩展名(.md);
  ContentField 带 ext;4 个 kind schema 各加可选 slides/transcript
- cph-model: Step::AssembleMarkdown{field} + manifest "assemble-markdown" 解析
- cph-check: run_markdown_assemble_target / target_is_markdown_assemble
  (照 run_shell_target 形状:check 门控、注入 h1、按 [[parts]] 序拼、写盘后
  收集 ![](rel) 引用图进 build 根使产物自包含、引用图缺失属 build-过程错误
  不入 6 类诊断);compile_targets 已 filter TypstCompile,纯 assemble 自然排除
- cph-cli: run_markdown_assemble_build 路由
- cph-typst: template_step 补 AssembleMarkdown => None 分支

测试:全 workspace 49 passed(新增 6 个 markdown 装配测试含图收集);
lake build 25 jobs 绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:55:55 +08:00
sjfhsjfh 9590e15236 feat(checker+typst): 嵌入 render 使 cph 可 cargo install;实现 shell step 执行器(ADR-0013)
三件事,服务于"把恒一小奥 KenKen 课作者化为合法 native 工程文件"这条主线
(工程文件本身在 repo 外的 sibling playground,不入此提交):

1. cph-typst: 把 render/ 编译期嵌入二进制,`cargo install` 后开箱即用
   - build.rs 把 render/ 拷进 OUT_DIR,剔除 dev 自指符号链接 vendor/local-packages
     (否则 include_dir! 无限递归)
   - embedded.rs 用 include_dir! 嵌入,运行时按版本解压到 per-user cache dir
     (CPH_RENDER_DIR 仍优先作 dev override)
   - default_render_dir 不再用编译期 CARGO_MANIFEST_DIR 写死路径

2. cph-check + cph-cli: 实现 Step::Shell 执行器(此前仅占位)
   - run_shell_target: 跑 check 门控 → 以工程根为 cwd 执行 shell step,首非零退出即停
   - target_is_shell + CLI run_shell_build 路由;`check` 不跑 shell(结构校验只看 lesson)
   - compile_targets 只保留含 TypstCompile 的 target,纯 shell target 不走 typst 引擎
   - 语义:失败属 build-过程错误,不入 6 类诊断(taxonomy 保持 6,显式拒绝加 ShellStep 码)

3. spec + ADR: 在 Export/Render.lean 钉 shell step 执行语义 prose;
   ADR-0013(已实现)、ADR-0014(md/HTML 导出后端方向,Proposed/设计先行,未实现)

测试:全 workspace 42 passed(新增 4 个 shell 执行器测试);lake build 25 jobs 绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:09:49 +08:00
sjfhsjfh c684d25d50 chore(spec+checker): cleanup pass — trim docs, reorg Courseware, covers-as-data, fold DanglingReference (ADR-0012)
Spec母本噪音清理 + 一处 spec↔impl 对齐 + 一处契约自洽修正。

Part A — spec doc 瘦身:每条 doc 收到"语义点 + 标签 + ADR ref + 承载性 why",
把跨文件复读的方法论(element-kind 开放性对比、likec4 画不出、分歧点测试)上移到
module header。OPEN 框架保持清晰(RunState/Capability 完整性仍明示须 surface)。

Part B — Courseware/ 由 10 文件平铺重组为 Model/ Export/ Check/ Open/ 四子命名空间
(namespace Spec.Courseware 不变,零引用改动)+ 四个子 aggregator。lake build 绿(24 jobs)。

Part C — 渲染覆盖落为数据(ADR-0011 对齐):去掉 cph-check 里硬编码的
COVERED_TARGETS,改读 TargetConfig.covers。cph-model 新增 covers: Option<Vec<String>>
(None=未声明,由 cph-check 默认为全部 known kinds;显式 [] 表示不覆盖任何 kind)。
新增 3 个覆盖行为测试。

ADR-0012 — DanglingReference 退役(诊断 7→6 类):其两种情形(未解析 @ref、越界/缺失
相对 import)都是 typst 编译期失败,归 typstCompile。同步移除 Oracle.refsResolve
(被 compiles 蕴含),Legal 少一个合取项。impl 删去从未被发射的 DiagCode::DanglingReference,
闭合 named-but-unemitted 的 spec↔impl 缝。ADR-0010 加修订指针。

OPEN 点(RunState/Capability 完整性、QuestionBank、Course)按既定纪律保持 OPEN,本次
只改善其框架措辞,不决策。

验证:spec lake build 绿;cargo test 全绿(含新增覆盖测试);clippy 静默;
TH-141 check 0 errors/0 warnings 无回归。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 23:59:32 +08:00
sjfhsjfh bd1699a4c0 feat(checker): align cph-typst + cph-check to export-as-build model (WU-D)
Integrate the WU-B (structured targets) and WU-C (numbly, config) changes.

cph-typst:
- World resolves any @preview/* package from the in-repo vendored dir
  (<render_dir>/vendor/typst-packages/preview/<name>/<version>/), fully offline —
  no typst-kit download. Proven: build_pdf_with_real_render compiles the real
  render package (which imports @preview/numbly:0.1.0) through the embedded
  engine, PDF out.
- Driver threads each target's presentation config: looks up the TargetConfig by
  name, emits `config: (numbering: (heading: (...)))` (escaped) when an override
  is present, else `config: (:)` (render default).
- target_precheck guards artifact/target: FileTree → blocking diagnostic (MVP is
  single-file, deferred per ADR-0009); --target not declared → blocking
  diagnostic; no-targets lesson still defaults through.

cph-check:
- Migrated to Lesson.targets: Vec<TargetConfig> (target_names() / target.name at
  the 6 sites). Pipeline unchanged (already matches ADR-0010 phases). Documented
  that !has_errors() implements Spec.Courseware.Legal (no error-level diagnostic).

Workspace: fmt + clippy -D warnings + all tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 08:47:13 +08:00
sjfhsjfh b86ee24a26 feat(checker): cph-check orchestrator + cph-cli cph binary (WU-5)
Closes the core pipeline: the `cph` CLI checks an engineering file and compiles
a PDF.

cph-check — phases (a) load → (b) structural (known-kind set) → (c) schema →
(d) typst compile → (e) render-coverage. Compile is gated: skipped if (a)-(c)
produced any Error (broken input would only add noise); `check` compiles every
declared target (dedup identical diags), `build` compiles the one requested.
Render-coverage emits a non-blocking RenderIgnored *warning* when a (kind,
target) has no render rule — severity pinned via RENDER_IGNORED_SEVERITY const
citing spec Diagnostic.renderIgnoredSeverity + ADR-0005. No double-emit:
unknown/missing parts are skipped downstream. API: check(root, engine) ->
CheckReport, build(root, engine, target) -> (Option<pdf>, CheckReport).

cph-cli — clap: `cph check <path>` (exit 1 on any Error, warnings → 0) and
`cph build <path> --target <name> [-o out]` (default target student, default
out <path>/build/<target>.pdf). Diagnostics → stderr via Display, results →
stdout. --render-dir override.

End-to-end on examples/TH-141 (39 parts): `check` → 0 errors/0 warnings;
`build` → real PDF student 9pp/395KB, teacher 12pp/474KB. Broken-element check
(unclosed delimiter in a stmt.typ) → span-accurate
`error[E-TYPST-COMPILE]: unclosed delimiter --> lemmas/…/stmt.typ:7:8`, exit 1.
Workspace: fmt + clippy -D warnings + test all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 01:57:34 +08:00
sjfhsjfh c810ea6137 feat(checker): scaffold repo-root cargo workspace + cph-diag + cph-model (WU-1)
Stand up the Rust implementation of the rule-based checker (the thing that
"stands in Lean's position" at product runtime). Single repo-wide cargo
workspace at the repo root so future components (e.g. an exporter) can reuse
shared crates.

- workspace: 6 member crates under crates/; cph-schema/cph-typst/cph-check/
  cph-cli are stubs for later WUs that compile clean today.
- cph-diag: shared diagnostic vocabulary. Severity { Warning, Error } mirrors
  Spec.Courseware.Diagnostic.Severity exactly (two-valued, no info/note — a
  contract decision documented in-code since there's no CI gate for alignment).
  Closed DiagCode set with stable string forms; Diagnostic with optional span +
  fix hint; Display renders `error[CODE]: msg / --> file:line:col / hint: …`.
- cph-model: the ADR-0008 loader. Reads manifest.toml ([project]/[info]/ordered
  [[parts]]/[targets.*]) + each part's element.toml into an ordered Lesson
  (mirrors Lean `Lesson = List (Element P)`). Structure-only: cross-checks
  part.kind == element.toml kind, rejects `..` traversal; does NOT do schema
  validation (WU-3), content-file existence (WU-3), or typst (WU-4).
  `load(root) -> (Option<Lesson>, Vec<Diagnostic>)`: Some even on collectible
  part errors, None only on hard manifest failure.
- 13 tests (7 cph-diag, 6 cph-model incl. static fixtures doubling as format
  docs). build + test + clippy -D warnings + fmt --check all green.

Judgment call flagged for review: cph-diag has no ManifestMalformed code, so
manifest-structure errors map to SchemaViolation (TODO noted in-code).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 01:27:32 +08:00