CB-WP-0046: the rule the placement encodes, and a log that names its rules
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
CB-WP-0045 left "nothing explains what a scope does" open and gave a FALSE reason: that scoping is our Variant so no printed sentence exists. The H2 package ships Rules_Text.csv -- twenty-two passages of player-facing rules -- and nothing in clay-borg had ever read the file. A wrong reason for an open item is worse than an open item; it retires the question. Filed as F26 against ground-game: a package that adds a FILE is invisible where one that adds a column is not. The scope rule now renders under the table in the edition's own words, only when a non-global scope is in play, matched by heading rather than row number, and absent (never paraphrased) if the edition drops it. The trial log stamps its variant on the begin marker -- a session property, not an eighth column -- read off state.variant rather than the --variant flag, because a bare `state.variant = v` leaves H2 inert and a flag-stamped log would put false provenance on real player words. An unstamped log reports `unrecorded`, never `ground-darvo-r0`. Six mutations, six red. The sixth is the finding: every trials.py fixture built its marker out of BEGIN, so nine checks followed BEGIN away from what hotseat.rs writes and stayed green while real logs broke. A fixture built from the constant under test cannot test the constant -- the control is now a literal, asserted from both sides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
df65e2dee1
commit
de25c4cae0
10 changed files with 986 additions and 12 deletions
|
|
@ -82,6 +82,16 @@ const GLOSSARY_CSV: &str = include_str!("../../../editions/ground-darvo-r0/Gloss
|
|||
/// H2's Problems table (CB-WP-0042). r0's with one column added.
|
||||
const H2_PROBLEMS_CSV: &str =
|
||||
include_str!("../../../editions/experiments/h2-scoped-problem-stress/Problems.csv");
|
||||
/// H2's player-facing rulebook. **It was here all along** (CB-WP-0046).
|
||||
///
|
||||
/// CB-WP-0045 recorded that nothing explains what a *scope does* and
|
||||
/// judged it a `ground-game` question, on the reasoning that scoping is
|
||||
/// clay-borg's Variant and so has no printed sentence. That was wrong:
|
||||
/// the package ships `Rules_Text.csv`, and row 20 is the rule in the
|
||||
/// edition's own words. **We had never read the file** — the third time
|
||||
/// this pass that vendored text could not reach a player (F18).
|
||||
const H2_RULES_TEXT_CSV: &str =
|
||||
include_str!("../../../editions/experiments/h2-scoped-problem-stress/Rules_Text.csv");
|
||||
|
||||
/// A vendored CSV, parsed into rows addressable by column name.
|
||||
///
|
||||
|
|
@ -562,6 +572,59 @@ pub fn stress_scopes(scenario_id: &str) -> Result<BTreeMap<u8, StressScope>, Str
|
|||
Ok(out)
|
||||
}
|
||||
|
||||
/// One passage of the variant's rulebook (CB-WP-0046).
|
||||
pub struct RulesPassage {
|
||||
pub order: u32,
|
||||
pub section: String,
|
||||
pub heading: String,
|
||||
pub body: String,
|
||||
}
|
||||
|
||||
/// H2's rulebook, in `Rules_Text.csv` order.
|
||||
///
|
||||
/// Returned whole rather than as a lookup by heading: a caller that wants
|
||||
/// the scope rule asks for its section, and the ordering is the
|
||||
/// edition's, not one we impose.
|
||||
pub fn h2_rules_text() -> Result<Vec<RulesPassage>, String> {
|
||||
let t = Table::parse(H2_RULES_TEXT_CSV, "h2/Rules_Text.csv")?;
|
||||
let mut out = Vec::new();
|
||||
for row in &t.rows {
|
||||
out.push(RulesPassage {
|
||||
order: t
|
||||
.get(row, "order")?
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(|_| "order is not a number".to_string())?,
|
||||
section: t.get(row, "section")?.to_string(),
|
||||
heading: t.get(row, "heading")?.to_string(),
|
||||
body: t.get(row, "body")?.to_string(),
|
||||
});
|
||||
}
|
||||
if out.is_empty() {
|
||||
return Err("h2/Rules_Text.csv has no rows".into());
|
||||
}
|
||||
out.sort_by_key(|p| p.order);
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// What a `stress_scope` DOES, in the edition's words (CB-WP-0046).
|
||||
///
|
||||
/// The passage headed *Stress scope* in the `Problems` section. Matched
|
||||
/// on the heading rather than pinned to row 20, because a row number is
|
||||
/// a property of today's file and the heading is a property of the rule.
|
||||
/// **`None` if the edition stops carrying it** — an absent explanation is
|
||||
/// reported as absent, never replaced by ours (ADR-0018).
|
||||
pub fn stress_scope_rule() -> Option<String> {
|
||||
h2_rules_text()
|
||||
.ok()?
|
||||
.into_iter()
|
||||
.find(|p| {
|
||||
p.section.eq_ignore_ascii_case("Problems")
|
||||
&& p.heading.to_lowercase().contains("stress scope")
|
||||
})
|
||||
.map(|p| p.body)
|
||||
}
|
||||
|
||||
/// The stress gate, printed on every player mat (CB-WP-0037 T03).
|
||||
///
|
||||
/// **A mat is mostly ornamentation with one rule on it.** Symbol, colour
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue