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>
74 lines
3.7 KiB
Markdown
74 lines
3.7 KiB
Markdown
# ADR 0007: The Engineering File Is A Directory Tree On Disk
|
|
|
|
## Status
|
|
|
|
Accepted — for the on-disk decision below. The concrete layout conventions are
|
|
deliberately left open; see *Open Questions / Deferred*.
|
|
|
|
Grounds the abstract premise ADR-0006 relied on. ADR-0006 established that rich
|
|
content needs a **virtual path** and that the engineering file therefore
|
|
constitutes a path-structured virtual file system — but it deliberately did not
|
|
say what that path structure *is* physically. This ADR fixes that: it is a real
|
|
directory tree on a real file system.
|
|
|
|
## Context
|
|
|
|
ADR-0006 showed that a rich-content (`content`) value cannot be free-floating
|
|
Typst source: it must be a first-class file with a virtual path so that
|
|
click-to-jump (spans) and relative imports work. That leaves a choice for the
|
|
physical form of the engineering file: a packed/opaque archive, a database blob,
|
|
or a plain directory tree.
|
|
|
|
The decisive constraint is **who edits the engineering file**: a coding agent
|
|
(Claude) collaboratively with teachers (ADR-0005's premise), and ordinary tools.
|
|
An agent works best when it can read and modify files directly and use existing
|
|
tooling (`grep`, `find`, diff, version control) over plain files in plain
|
|
directories. A packed or database form would force a custom access layer for
|
|
every such operation.
|
|
|
|
The developer's earlier prototype already had this shape implicitly —
|
|
`segments/`, `examples/`, `lemmas/` directories with per-item files — which is
|
|
the directory tree in embryo, not a crude stand-in.
|
|
|
|
## Decision
|
|
|
|
The on-disk form of an engineering file is a **directory tree** on a real file
|
|
system.
|
|
|
|
- A `content` field's **virtual path** (ADR-0006) is a **real relative path**
|
|
within that directory tree. The compiler's `World` maps virtual paths to the
|
|
actual files in the tree; no synthetic/in-memory file system is needed.
|
|
- Relative imports inside rich content resolve relative to the importing file's
|
|
real position in the tree — which is exactly the import boundary ADR-0006
|
|
pinned ("within the engineering file, plus `@package`"). This ADR gives that
|
|
boundary its physical basis: "within the engineering file" = "within this
|
|
directory tree".
|
|
|
|
This keeps the engineering file legible to agents and to off-the-shelf tooling,
|
|
and makes the relationship between content fields and their sources directly
|
|
inspectable on disk.
|
|
|
|
## Consequences
|
|
|
|
- The engineering file is a directory of plain text/Typst files: directly
|
|
greppable, diffable, version-controllable, and editable by an agent without a
|
|
bespoke access layer.
|
|
- `World` is a thin mapping from the directory tree; virtual path = relative path
|
|
removes any need to invent or maintain a separate virtual file system.
|
|
- The engineering file remains self-contained on disk: its import closure is the
|
|
tree itself plus published packages (ADR-0006), so it can be moved, copied, or
|
|
archived as a directory without dangling references to sibling lessons.
|
|
- This is the **physical representation** of ADR-0005's abstract `Lesson` (an
|
|
ordered sequence of typed elements); how that ordered structure is encoded into
|
|
the directory is a separate question (below), not implied by "it's a tree".
|
|
|
|
## Open Questions / Deferred
|
|
|
|
- **Layout conventions** — the concrete directory layout is *not* fixed here.
|
|
Specifically deferred: the manifest file (name, location, what it holds); how
|
|
element instances are arranged in the tree and how their **order** (ADR-0005's
|
|
`Lesson` is an ordered sequence) is encoded; naming/organization of
|
|
rich-content `.typ` files. This is the on-disk encoding of ADR-0005's `Lesson`
|
|
and warrants its own ADR — kept separate so this one fixes only "it is a
|
|
directory tree", not "how the tree is arranged".
|