Vapora/adrs/adr-constraints.ncl
Jesús Pérez 75e5ebd9a2
Some checks failed
Documentation Lint & Validation / Markdown Linting (push) Has been cancelled
Documentation Lint & Validation / Validate mdBook Configuration (push) Has been cancelled
Documentation Lint & Validation / Content & Structure Validation (push) Has been cancelled
mdBook Build & Deploy / Build mdBook (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
Documentation Lint & Validation / Lint & Validation Summary (push) Has been cancelled
mdBook Build & Deploy / Documentation Quality Check (push) Has been cancelled
mdBook Build & Deploy / Deploy to GitHub Pages (push) Has been cancelled
mdBook Build & Deploy / Notification (push) Has been cancelled
chore: ontology sync + 4 NCL ADRs + landing page update
on+re:
  - core.ncl: 5 new Practice nodes (notification-channels,
    vapora-capabilities, agent-hot-reload-stable-identity,
    merkle-audit-trail, notification-channels) + 5 new edges;
    knowledge-graph-execution-history updated with HNSW+BM25+RRF
  - state.ncl: production-readiness blocker/catalyst updated (hot-reload
    complete, BudgetManager/LLMRouter still require restart);
    ontoref-integration catalyst updated (vapora-ontology/reflection
    crates, api-catalog.json, nickel contracts)

  ADRs (NCL):
  - adr-013: KG hybrid search — HNSW+BM25+RRF, rejected in-process scan
  - adr-014: capability packages — AgentDefinition→vapora-shared,
    DashMap shard-before-await constraint
  - adr-015: Merkle audit trail — SHA-256 hash chain, rejected HMAC
  - adr-016: agent hot-reload — stable_id=role, learning_profiles survive
    drain, BudgetManager excluded from reload scope

  landing page:
  - 2 new feature boxes: VCS-Agnostic Worktree (jj/git), Ontology Protocol
  - KG box: 20→28 tests, HNSW+BM25+RRF description
  - Agents box: 71→82 tests, hot-reload + stable_id
  - tech stack: Rust 21→23 crates, added jj, Radicle, ontoref badges
  - status badge: 620→691 tests
2026-04-07 21:06:48 +01:00

51 lines
1.5 KiB
Text

let _adr_id_format = std.contract.custom (
fun label =>
fun value =>
if std.string.is_match "^adr-[0-9]{3}$" value then
'Ok value
else
'Error {
message = "ADR id must match 'adr-NNN' format (e.g. 'adr-001'), got: '%{value}'"
}
) in
let _non_empty_constraints = std.contract.custom (
fun label =>
fun value =>
if std.array.length value == 0 then
'Error {
message = "constraints must not be empty — an ADR with no constraints is passive documentation, not an active constraint"
}
else
'Ok value
) in
let _non_empty_negative = std.contract.custom (
fun label =>
fun value =>
if std.array.length value.negative == 0 then
'Error {
message = "consequences.negative must not be empty on id='%{value.id}' — an ADR with no negative consequences is incomplete"
}
else
'Ok value
) in
let _requires_justification = std.contract.custom (
fun label =>
fun value =>
if value.ontology_check.verdict == 'RequiresJustification
&& !(std.record.has_field "invariant_justification" value) then
'Error {
message = "ADR '%{value.id}': ontology_check.verdict = 'RequiresJustification but invariant_justification field is missing"
}
else
'Ok value
) in
{
AdrIdFormat = _adr_id_format,
NonEmptyConstraints = _non_empty_constraints,
NonEmptyNegativeConsequences = _non_empty_negative,
RequiresJustificationWhenRisky = _requires_justification,
}