Skip to content

validate

validate checks a security assessment file against the schema record sends it under, and reports every problem in one run.

Terminal window
ingrain validate --assessment <path> [--json]

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.

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.

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.

Some checks span sections, so no single writer of the file ever sees them:

  • Every ## Org rules entry carries a gate decision — selected or excluded.
  • Every Rule refs id names a selected rule.
  • Every ## Rule adherence entry 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 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 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.

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.

CodeMeaning
0Valid, or an untouched skeleton. Warnings and information do not fail it.
1The file has problems that must be fixed before it can sync.
2Bad arguments — a missing --assessment, or a file that is not there.

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 versionBehaviour
absent or 1A 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.
2The 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 2Accepted, with unrecognised fields ignored — a newer skill must never break an older CLI.