1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Whether a builtin's effect was *decided* or merely *defaulted*.
//!
//! `effect_of` falls through to `Effect::Pure`, which is the right default for
//! policy and the wrong one for disclosure: it renders "nobody has classified
//! this" and "this was read and found harmless" as the same string. An agent
//! choosing how much to trust `x-effect: pure` cannot tell them apart, and the
//! difference is exactly the one that matters to it.
use aethershell::builtins::BUILTIN_LOOKUP;
use aethershell::safety::{effect_is_declared, effect_of, Effect};
#[test]
fn a_declared_effect_and_the_fallthrough_are_distinguishable() {
// `rm` is classified; a name nothing matches is not. Without this the two
// are the same `Pure`-shaped answer.
assert!(effect_is_declared("rm"), "rm is explicitly classified");
assert!(
!effect_is_declared("definitely_not_a_builtin_xyzzy"),
"an unknown name must report as undeclared, not as declared-pure"
);
}
#[test]
fn every_effecting_class_is_declared_rather_than_defaulted() {
// The fall-through can only ever produce `Pure`. So anything reported as
// acting must have come from a rule — if this ever fails, the fall-through
// has been changed to something that acts, and every unclassified builtin
// silently became dangerous (or silently gated).
for name in BUILTIN_LOOKUP.keys() {
let eff = effect_of(name);
if eff != Effect::Pure {
assert!(
effect_is_declared(name),
"{name} reports {eff:?} but is not declared — the fall-through now acts"
);
}
}
}
#[test]
fn the_undeclared_population_is_reported_not_hidden() {
// Not an assertion about the number: it is debt, and pinning it would just
// make the number a thing to satisfy. Printing it keeps it visible, which
// is the property that was missing when 28 misclassifications accumulated.
let total = BUILTIN_LOOKUP.len();
let declared = BUILTIN_LOOKUP
.keys()
.filter(|n| effect_is_declared(n))
.count();
eprintln!(
"effect provenance: {declared}/{total} declared, {} fall through to Pure ({:.0}%)",
total - declared,
100.0 * (total - declared) as f64 / total as f64
);
assert!(
declared > 0,
"no builtin is declared — the table is not wired"
);
}
#[test]
fn today_every_pure_is_the_fallthrough_and_none_is_a_finding() {
// Written expecting the opposite, and corrected by the result: the match
// has no `Pure` arm at all. So `x-effect: pure` does not mean "read and
// found harmless" for *any* builtin today -- it means "not classified",
// uniformly, for all 694 of them.
//
// Worth pinning rather than fixing quietly. If someone later classifies a
// builtin as genuinely Pure, this test fails and asks them to say so --
// at which point `pure` carries two meanings again and
// `effect_is_declared` becomes the only way to separate them.
let declared_pure: Vec<&str> = BUILTIN_LOOKUP
.keys()
.filter(|n| effect_of(n) == Effect::Pure && effect_is_declared(n))
.copied()
.collect();
assert!(
declared_pure.is_empty(),
"{} builtin(s) are now explicitly classified Pure: {:?}. This is an improvement, not a regression -- update this test to name them, and note that `x-effect: pure` now means two different things which only `x-effect-declared` separates.",
declared_pure.len(),
&declared_pure[..declared_pure.len().min(10)]
);
}
// ── The disclosure convention ───────────────────────────────────────────────
#[test]
fn the_ontology_flags_only_the_undeclared_and_absence_means_declared() {
// `effect_declared` is emitted only when false. That is a deliberate
// asymmetry -- it halves the cost on the full-detail dump (+4.7% instead
// of +9.2%, measured) and only one direction is actionable. But it means
// *absence carries meaning*, which is exactly the kind of convention that
// rots into "the field is missing, so who knows" without a test.
use aethershell::agent_api::ontology_describe_json;
let unclassified = ontology_describe_json("upper");
assert_eq!(unclassified["effect"], "pure");
assert_eq!(
unclassified["effect_declared"], false,
"an unclassified builtin must carry the flag, or agents cannot tell \
a default from a finding"
);
for name in ["sh", "ls", "cat"] {
let classified = ontology_describe_json(name);
assert!(
classified.get("effect_declared").is_none(),
"{name} is classified, so the flag must be absent -- emitting it \
as `true` is the cost this convention exists to avoid"
);
}
}
#[test]
fn the_readers_reclassified_from_pure_report_read_local() {
// The 55 found by body evidence. Spot-checked here so a future edit to the
// match cannot quietly return them to `pure` -- which would restore the
// claim that `ls` is referentially transparent.
use aethershell::safety::{effect_of, Effect};
for name in [
"ls", "cat", "head", "tail", "grep", "wc", "fs_stat", "env_var",
] {
assert_eq!(
effect_of(name),
Effect::ReadLocal,
"{name} observes local state and must not advertise as Pure"
);
}
}