ontoref-code/domains/framework/ontology/constraints.ncl
2026-07-10 01:44:59 +01:00

50 lines
1.4 KiB
Text

# domains/framework/ontology/constraints.ncl
# Shared mode constraints for Library, Service, and Tool projects.
# Projects import via:
# let c = import "framework/ontology/constraints.ncl" in
let _non_empty_steps = std.contract.custom (
fun label =>
fun value =>
if std.array.length value.steps == 0 then
'Error {
message = "Mode '%{value.id}': steps must not be empty — a mode with no steps is passive documentation, not an executable contract"
}
else
'Ok value
) in
let _valid_trigger = std.contract.custom (
fun label =>
fun value =>
if std.string.length value.trigger == 0 then
'Error {
message = "Mode '%{value.id}': trigger must not be empty — it identifies how this mode is invoked"
}
else
'Ok value
) in
let _non_empty_cmds = std.contract.custom (
fun label =>
fun value =>
let bad = value.steps
|> std.array.filter (fun s =>
std.record.has_field "cmd" s
&& std.string.length (std.string.trim s.cmd) == 0
)
|> std.array.map (fun s => s.id)
in
if std.array.length bad > 0 then
'Error {
message = "Mode '%{value.id}': steps with empty cmd: %{std.string.join ", " bad}"
}
else
'Ok value
) in
{
NonEmptySteps = _non_empty_steps,
ValidTrigger = _valid_trigger,
NonEmptyCmds = _non_empty_cmds,
}