validate
validate checks a security assessment file against the schema
record sends it under, and reports every problem in one
run.
ingrain validate --assessment <path> [--json]What it reports
Section titled “What it reports”An untouched skeleton is not an error: the review has not written the file yet, and
validate says so and exits 0.
Otherwise every problem carries a severity, and only one of them stops a sync:
- error — must be fixed. Either a value outside its allowed set, or a field the current stage owes and has not written. The report groups the two separately.
- warning — the file syncs, with something lost or suspect.
- information — nothing to fix. An accepted driver whose verification has not reached it yet.
Each problem names the entry, the field, the allowed values, and the section whose field card documents it — the comment seeded under each heading in the file you already have open.
The anchoring rule
Section titled “The anchoring rule”Every ## Implementation guidance entry names at least one driver — a threat it
closes (Threats) or an org rule it implements (Rule refs). Either may be —, but
not both; an entry naming neither is an error here and at the platform.
Naming a rule and no threat is fine.
Phase blocks
Section titled “Phase blocks”A ## Threats entry groups its fields under #### gen, #### score, #### usergate
and #### test — one marker per stage of the review. The review writes them; you rarely
need to touch them by hand.
If validate reports a problem here, it is one of these, and each names the entry:
- A verification field sits outside
#### test— move it under that marker. Left where it is, a later stage of the review overwrites it. - An unrecognised marker, such as
#### tset— correct it to one of the four. - A repeated marker, or a marker in a section that has none — keep one of each, and
only on
## Threats.
Assessments written without markers work unchanged.
Cross-section checks
Section titled “Cross-section checks”Some checks span sections, so no single writer of the file ever sees them:
- Every
## Org rulesentry carries a gate decision —selectedorexcluded. - Every
Rule refsid names a selected rule. - Every
## Rule adherenceentry names a selected rule. - No duplicate adherence entries — one verdict per rule.
- A selected rule with no verdict yet is information, not an error: a half-run Testing pass syncs as it stands. A selected rule nothing implements is legal — Testing judges it anyway.
Affected paths
Section titled “Affected paths”## Affected paths declares the folders the change is expected to touch. It scopes
rule retrieval and attributes the analysis to part of the codebase, so a problem here
costs precision rather than correctness — every one is a warning, and none stops a
sync.
Reported, and dropped from the footprint:
- An absolute path (
/srv/app/services,C:\work\repo) — it names a place on your machine, not in the repository. - A
.or..segment. - The repository root (
.,/) — legal, but it narrows nothing.
Also reported: a major triage that declares no paths at all, since retrieval then
could not be narrowed to the change.
A folder already covered by a shallower one is folded away — declaring both
backend and backend/services/sync sends only backend.
Rule ids
Section titled “Rule ids”Rule ids resolve against the assessment’s own ## Org rules section — the same file,
a few headings up. One artifact, one id space; there is no sidecar to pass.
Ids are exact-match keys, so an id shortened to a prefix resolves but is reported — it must be
written in full, since a truncated copy resolves to nothing downstream. Below Schema version: 2
that is a warning, the drift being a known trait of older releases; from version 2 the skill
guarantees full ids, so it is an error.
An id matching no ## Org rules entry is an error — the sync refuses it too.
--json
Section titled “--json”Machine output goes to stdout, human output to stderr, so --json pipes
cleanly.
{ "state": "invalid", "ok": false, "problems": [ { "severity": "error", "kind": "malformed", "where": "T01", "field": "Impact", "message": "Impact must be one of: critical | high | medium | low — got \"catastrophic\"", "card": "## Threats" } ]}state is skeleton, ready or invalid; ok is false only for invalid.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Valid, or an untouched skeleton. Warnings and information do not fail it. |
1 | The file has problems that must be fixed before it can sync. |
2 | Bad arguments — a missing --assessment, or a file that is not there. |
Schema versions
Section titled “Schema versions”The assessment declares its own format under ## Task as Schema version, so the
CLI branches on a stated version instead of guessing from which fields are present.
| Declared version | Behaviour |
|---|---|
absent or 1 | A design sync is accepted with a fallback: a missing Description falls back to the title. A truncated rule id resolves with a warning. A verification is refused — version 1 predates the reasoning fields the verdict contract requires, so no Testing pass can produce a valid one; the fix is to upgrade the plugin. The old table layout fails loudly with an upgrade message at any version, being a structurally different artifact rather than a file missing fields. |
2 | The full schema is expected; the fallback above does not apply, so a genuinely missing field is reported rather than papered over. Full rule ids are guaranteed, so a truncated one is an error rather than a warning. |
above 2 | Accepted, with unrecognised fields ignored — a newer skill must never break an older CLI. |