diff --git a/bench/orchestrator-stats/2026-05-20-iter-bugfix-drift-anchor-scope.json b/bench/orchestrator-stats/2026-05-20-iter-bugfix-drift-anchor-scope.json new file mode 100644 index 0000000..49819e1 --- /dev/null +++ b/bench/orchestrator-stats/2026-05-20-iter-bugfix-drift-anchor-scope.json @@ -0,0 +1,12 @@ +{ + "iter_id": "bugfix-drift-anchor-scope", + "date": "2026-05-20", + "mode": "mini", + "outcome": "DONE", + "tasks_total": 1, + "tasks_completed": 1, + "reloops_per_task": { "1": 0 }, + "review_loops_spec": 0, + "review_loops_quality": 0, + "blocked_reason": null +} diff --git a/crates/ailang-core/tests/design_schema_drift.rs b/crates/ailang-core/tests/design_schema_drift.rs index 4315df3..3e9f912 100644 --- a/crates/ailang-core/tests/design_schema_drift.rs +++ b/crates/ailang-core/tests/design_schema_drift.rs @@ -21,6 +21,31 @@ use ailang_core::ast::{ const DATA_MODEL: &str = include_str!("../../../design/contracts/data-model.md"); +/// Scoped substring match: returns `true` iff `anchor` appears inside a +/// fenced code block (``` or ~~~) of `md`. Info-string `jsonc` / `json` / +/// unspecified all count — fence-toggling is by fence-marker line alone, +/// mirroring the inverse `strip_fences` pattern in +/// `crates/ailang-core/tests/design_index_pin.rs`. The whole-file +/// `.contains()` was fidelity-widened: anchors mentioned in surrounding +/// prose (footnotes, inline references, historical notes) counted as +/// present, so a future edit could delete the canonical schema entry for +/// a variant from inside a fenced block and the drift test would still +/// pass. This helper closes that surface. +fn anchor_in_jsonc_block(md: &str, anchor: &str) -> bool { + let mut in_fence = false; + for line in md.lines() { + let t = line.trim_start(); + if t.starts_with("```") || t.starts_with("~~~") { + in_fence = !in_fence; + continue; + } + if in_fence && line.contains(anchor) { + return true; + } + } + false +} + /// Every `Term` variant must have its JSON-schema anchor present in /// design/contracts/data-model.md. An LLM author cannot produce a term variant /// whose `"t"` tag is absent from the canonical schema document. @@ -156,7 +181,7 @@ fn design_md_anchors_every_term_variant() { Term::Recur { .. } => "recur", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a Term variant — \ add it to design/contracts/data-model.md" ); @@ -186,7 +211,7 @@ fn design_md_anchors_every_pattern_variant() { Pattern::Ctor { .. } => "ctor", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a Pattern variant" ); } @@ -219,7 +244,7 @@ fn design_md_anchors_every_type_variant() { Type::Forall { .. } => "forall", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a Type variant" ); } @@ -248,7 +273,7 @@ fn design_md_anchors_every_literal_variant() { Literal::Float { .. } => "float", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a Literal variant" ); } @@ -320,7 +345,7 @@ fn design_md_anchors_every_def_kind() { Def::Instance(_) => "instance", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a Def kind" ); } @@ -344,7 +369,7 @@ fn design_md_anchors_every_parammode_variant() { ParamMode::Borrow => "borrow", }; assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing anchor `{anchor}` for a ParamMode variant" ); } @@ -457,7 +482,7 @@ fn design_md_anchors_nested_struct_keys() { for anchor in anchors { assert!( - DATA_MODEL.contains(anchor), + anchor_in_jsonc_block(DATA_MODEL, anchor), "design/contracts/data-model.md is missing nested-struct-key anchor `{anchor}`" ); }