Skill 05 · Wp Abilities Verify
Subchapter 5.2
references/audit-schema-validation.mdMarkdown5 KBView on GitHub
How wp-abilities-verify validates an audit document produced by
wp-abilities-audit. The canonical schema (field tables, types,
invariants, known limitations) lives in
../../wp-abilities-audit/references/audit-schema.md — this reference
covers only the validation procedure: how to extract the YAML, what
checks to run in what order, and how to report results.
If a field type or shape question is not answered here, look in the canonical schema. Do NOT duplicate field tables in this file — the canonical is the single source of truth.
Verify fails fast on a malformed audit so the rest of its procedure can assume well-formed input. Audit produces; verify validates the production. Co-locating the validator with verify keeps the “validate audit” step in the same procedure as “validate registered abilities” and lets a single run produce one consolidated report.
The audit doc is a markdown file with a single fenced ```yaml block
containing the structured fields:
# Scan for the ```yaml fence and capture until the closing ``` fence.
awk '/^```yaml$/{f=1;next} /^```$/{f=0} f' <audit-doc.md> > /tmp/audit.yamlIf the audit has multiple YAML blocks (it shouldn’t, but defensively),
take the first one with proposed_abilities as a top-level key.
Parse with any YAML library — js-yaml from Node, yaml (Python), or
yq from the command line. None of the canonical fields require
non-standard YAML features (no anchors, no aliases), so a plain
yaml.load is sufficient.
Apply the field-shape rules defined in
../../wp-abilities-audit/references/audit-schema.md. Specifically:
capability_gate matches one of the legal shapes (single string,
{read, write} object, or — with WARN per the canonical’s “Known
limitations” — the legacy slash-separated string).proposed_abilities has every required per-ability
field with the right type (see “proposed_abilities“ in the
canonical).annotations block has all three booleans
(readonly, destructive, idempotent) as actual booleans —
string "true" / "false" is FAIL (indicates a quoting bug).backing is either an object with the canonical
fields or null; null is WARN, not FAIL (it’s intentional gap
output).Missing required field → FAIL. Wrong type → FAIL. Legacy
capability_gate slash-string → WARN.
Run these after per-field validation passes:
Count abilities where reference_ability is true. More than 1 → FAIL
(the schema permits at most one reference; multiple are ambiguous for
implementers picking a starting point).
const refCount = audit.proposed_abilities.filter(a => a.reference_ability === true).length;
if (refCount > 1) fail("multiple abilities claim reference_ability: true");Per the canonical’s “Known limitations”: a null backing is intentional
gap output and MUST be paired with a matching surfaced_gaps entry.
const gapNames = new Set((audit.surfaced_gaps || []).map(g => g.name));
for (const ability of audit.proposed_abilities) {
if (ability.backing === null && !gapNames.has(ability.name)) {
fail(`ability ${ability.name} has backing: null but is missing from surfaced_gaps`);
}
}Both are optional; empty arrays are legal. Missing entirely → WARN (schema expects them, even if empty).
Each check goes into the “Audit doc validation” section of the run’s final report:
## Audit doc validation
| Check | Result | Detail |
|---|---|---|
| Top-level required fields | OK | All 7 required fields present |
| `capability_gate` shape | OK | string (single-cap) |
| Per-ability fields | WARN | 1 ability has `backing: null` (intentional) |
| `reference_ability` uniqueness | OK | 1 ability marked |
| `surfaced_gaps` consistency | OK | all `backing: null` entries present |A single FAIL in this section makes the whole run FAIL; verify cannot meaningfully continue without a trustworthy audit. WARN entries don’t block the rest of the procedure.
The procedure is manual-but-deterministic: follow the steps above in order, emit the report section, and fail fast on any missing required field. A future contribution may add a deterministic CLI helper that extracts the YAML fence and applies the rules end-to-end; until that exists, the steps above are the contract.
If the validator rejects an audit that’s actually well-formed, the
canonical schema in
../../wp-abilities-audit/references/audit-schema.md has evolved.
Update this file’s procedure to match (likely adding a new invariant
or relaxing a field rule). Don’t loosen the validation in isolation —
the canonical schema is the contract; this file is the enforcer.