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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// SPDX-License-Identifier: Apache-2.0
//! A Shape-origin check, generated from the facets a taxonomy declares
//! `type: string`.
//!
//! [`crate::facet_required`] reports a key that is absent, and
//! [`crate::facet_value`] reports a scalar outside a closed set. Neither one
//! reaches the state between them: the key is declared, and it carries no
//! content. That is the state
//! [#541](https://github.com/headwater-ai/headwater/issues/541) measured, where
//! a `title` written as `title:` reached a rendered shelf index as `[~]` at
//! exit 0 through every gate this engine has.
//!
//! Nothing below names a facet or a kind. The population is every facet whose
//! declaration says `type: string` and that the kind does not forbid, so a
//! taxonomy that types one more facet as a string gets one more facet read and
//! this file does not change.
//!
//! # The three families, and why one predicate is not enough
//!
//! The shapes a blank value takes come from the parser rather than from what
//! blank ought to mean, and there are three of them.
//!
//! `title:` with nothing after the colon, `title: ~`, and `title: null` are all
//! **plain null**. [`headwater_yaml::core_schema::as_null`] is the resolver for
//! them, and it is the reason this rule reads that function rather than a
//! predicate of its own: saphyr hands `title:` back as a plain scalar whose
//! text is the literal `~`, so a rule written as `text.trim().is_empty()` reads
//! it as content and lets the whole family through. That family is the one the
//! issue does not know about, and it is the one that renders.
//!
//! `title: ""`, `title: " "` and a block scalar with no content are **empty
//! text**. The author wrote a string and the string holds nothing. The two
//! families are held apart because the core schema holds them apart, which is
//! also why [`headwater_yaml::value::Scalar`] keeps its style.
//!
//! `title: []` and `title: {}` are **not a scalar at all**, where the
//! declaration says `string`. [`crate::facet_value`] declines that shape and
//! says so, because a value the meta-schema owns is not the check layer's to
//! type. It is reported here for the one facet family this rule already reads,
//! and the general question — whether `type:` binds a document facet value at
//! all — is a wider debt that
//! [spec 13](../../../../docs/spec/13-open-obligations.md) carries.
//!
//! # Where the finding reports, and why it offers no fix
//!
//! At the value, because that is the text to change. No fix is offered:
//! [spec 12](../../../../docs/spec/12-check-layer.md#fixability) makes one
//! mechanical only where there is one correct outcome derivable without
//! judgment, and the value of a blank `title` is a name somebody has to write.
//! Deleting the key is the other legal repair wherever the kind does not
//! require the facet, and the remediation names both, because an engine that
//! picked one would be making the author's choice.
//!
//! # Error, and not a warning
//!
//! Severity and fixability are separate axes here, and
//! [`crate::facet_required`] is the precedent: it offers no patch and carries
//! [`Severity::Error`] anyway. A missing name is an error and a blank one was
//! silent, which is the asymmetry the issue names, and the two states have to
//! land at the same severity or the asymmetry survives the fix.
//!
//! # One overlap, stated rather than removed
//!
//! A facet that declares both `type: string` and a closed value set is read by
//! this rule and by [`crate::facet_value`], and a blank value on one raises two
//! findings. Both are true, both are errors, and they name different repairs:
//! one says the key carries no content, the other names the admitted set. The
//! alternative is a rule whose population depends on a second declaration,
//! which is a narrowing no reader of the taxonomy could predict from it.
use crate;
use crateOutcome;
use crate;
use crateShape;
pub const RULE: &str = "facet.value.blank";
/// The type name this rule reads. A facet declaring any other type, or none, is
/// not in the population: the shapes below are what a *string* value may
/// degenerate into, and a blank date or a blank integer is a question about a
/// type this rule does not parse.
const STRING: &str = "string";
/// One string-typed facet a kind may carry, and whether that kind owes it.
/// Every string-typed facet one kind may carry.
/// The check, generated from the facet declarations.