Iter 13d: rustdoc polish for ailang-core + new docwriter agent

Adds ailang-docwriter to /agents/ — a recurring role for keeping
crate-, module-, and pub-item-level rustdoc accurate. First mission:
ailang-core. Crate root, every module root, every pub item documented;
intra-doc links throughout; Iter-13a additions (TypeDef.vars, Type::Con.args)
get an explicit backwards-compat note. Two stale broken-link warnings in
ailang-check fixed in passing. cargo doc --no-deps now warning-free across
the workspace; promoted to verification invariant 6 in DESIGN.md.
This commit is contained in:
2026-05-07 15:02:35 +02:00
parent 3d9fbc68c6
commit c90926dbba
12 changed files with 536 additions and 36 deletions
+36 -5
View File
@@ -1,14 +1,45 @@
//! Content-addressed hashing for definitions.
//!
//! Hash = BLAKE3 over the canonical JSON form (see `canonical`).
//! The `hash` field in the input is removed before hashing.
//! Hash = BLAKE3 over the canonical JSON bytes of a [`Def`] (see
//! [`crate::canonical`]). The hash function takes a [`Def`] by
//! reference, so there is no `hash` field to strip — the in-memory
//! struct does not carry one.
//!
//! The single entry point at this level is [`def_hash`]. The parallel
//! entry point at module granularity is
//! [`crate::workspace::module_hash`].
use crate::ast::Def;
use crate::canonical;
/// 16-hex-char (64-bit) prefix of the BLAKE3 hash.
/// Enough for uniqueness within realistic codebases and compact
/// enough for visual inspection.
/// Content hash of a single [`Def`] — the 16-hex-char (64-bit) prefix
/// of its BLAKE3 hash over canonical JSON bytes.
///
/// 64 bits is wide enough to be unique across realistic AILang
/// codebases and short enough to read at a glance in pretty-printed
/// manifests. The hash is computed over the **canonical JSON byte
/// pre-image**, not over the in-memory struct, so any change to the
/// canonical form (new fields, different `skip_serializing_if`
/// behaviour, key reordering bug) changes every hash. The Iter 13a
/// regression test below pins concrete hashes for two example
/// definitions to catch that.
///
/// # Examples
///
/// ```ignore
/// use ailang_core::{ast::*, def_hash};
///
/// let def = Def::Const(ConstDef {
/// name: "answer".into(),
/// ty: Type::int(),
/// value: Term::Lit { lit: Literal::Int { value: 42 } },
/// doc: None,
/// });
///
/// // Stable across runs: same canonical bytes -> same hash.
/// assert_eq!(def_hash(&def), def_hash(&def));
/// assert_eq!(def_hash(&def).len(), 16);
/// ```
pub fn def_hash(def: &Def) -> String {
let bytes = canonical::to_bytes(def);
let h = blake3::hash(&bytes);