Skip to content

F-9 + F-10 cleanup — schema lint + batch doctor helper

Was: state.schema.json#probe_history.detail enforces maxLength: 200 against details propagated from contract.yaml#…not_applicable_reason. A consumer-side reason longer than 200 chars was accepted at contract load (no upstream cap), then silently failed at write-state time inside the spine with an opaque Refusing to write invalid state to state/<slug>.yaml: /probe_history/4/detail: must NOT have more than 200 characters.

Fix: add maxLength: 200 to contract.schema.json#common_envelope.not_applicable_reason. AJV catches the violation at contract load with a precise pointer:

Invalid contract at .../<slug>/.petrova/contract.yaml:
/integrations/<name>/not_applicable_reason: must NOT have more than 200 characters

Spot-checked locally with a synthetic 250-char reason — error now points at the consumer’s contract field, not the spine. 158/158 tests still pass; no existing fixtures or contracts cross the 200-char threshold.

Was: petrova doctor --commit-state operates on one repo at a time; the CLI exits non-zero on per-repo failure. Operators running ad-hoc shell loops over governed slugs can miss partial failures unless they aggregate exit codes themselves. eva-hq’s failure during sub-project F’s bulk run was visible to stderr but missed in stdout tail.

Fix: add scripts/doctor-all.sh that:

  • Parses governed slugs from registry.yaml.

  • Runs node cli/dist/index.js doctor --repo <workspace>/<slug> --commit-state for each slug whose local clone has a .petrova/ dir.

  • Skips with a clear message when no contract exists yet.

  • Aggregates per-slug exit codes; exits 1 if any failed.

  • Prints a summary table:

    petrova-hq ok
    kahn-hq ok
    traceo-mcp-server skip (no .petrova/ at /home/devarno/code/workspace/traceo-mcp-server)
    summary: 8 ok, 1 skipped (no contract), 0 failed

Verified locally — all 8 contracted slugs report ok, traceo-mcp-server correctly skipped, exit code 0.

Lower-effort than wiring --all into the CLI; honest about being an operator script. If batch operation becomes a first-class need (e.g. CI runs it nightly), the natural follow-up is petrova doctor --all --workspace <path> mirroring this script’s behaviour.

  • F-9 + F-10 closed.
  • All 9 registry slugs are now reconcilable in one command: bash scripts/doctor-all.sh.
  • 8 of 9 have contracts; traceo-mcp-server (local clone is traceo-cat/, externally maintained) remains the only unbootstrapped slug — separate from F-9/F-10.