Skip to content

Assertion Authoring

Assertions encode design standards as structured, machine-evaluable rules. When the pipeline runs with assertions, it strips conformant values (saving tokens) and annotates deviations (highlighting what matters).

Assertion File Format

assertions:
- id: unique-identifier
assert: Human-readable description of the standard
rationale: Why this standard exists
severity: must
match:
path: services.*.image
pattern: "^(?!.*:latest$)"
example: "nginx:1.25.3"

Required Fields

FieldTypeDescription
idstringUnique identifier. Used in output, merge deduplication, and cross-references.
assertstringHuman-readable statement of the standard.
rationalestringWhy this standard exists.
severitystringmust, should, or may. Controls pipeline behavior.

Optional Fields

FieldTypeDescription
matchobjectMachine-evaluable condition (path + condition). Without it, assertion is LLM-context only.
examplestringConformant value example.
exceptionsstringCases where the assertion may be legitimately violated.
relatedlistIDs of related assertions.
sourcestringOrigin reference (standards document, policy ID).

Severity Levels

Levelstrip-conformantannotate-deviationsUse when
mustRemoves conformant valuesAnnotates violations with [!]Hard requirements every config must meet
shouldNo effectAnnotates violations with [!]Best practices where exceptions are expected
mayNo effectNo effectInformational standards for LLM context

Match Conditions

Each match requires a path and exactly one condition type.

value — Exact Match

Case-insensitive string comparison, or direct equality for other types.

- id: require-json-logging
assert: Logging driver must be json-file
severity: must
match:
path: services.*.logging.driver
value: json-file

pattern — Regex Match

Tested with re.search (matches anywhere unless anchored).

- id: image-pinned
assert: Image tags must be pinned to specific versions
severity: must
match:
path: services.*.image
pattern: "^(?!.*:latest$)(?=.*:.+$)"

range — Numeric Range (Inclusive)

Two-element list [min, max]. Value is converted to float.

- id: valid-port-range
assert: Exposed ports must be in the valid range
severity: must
match:
path: services.*.ports[*].published
range: [1, 65535]

contains — List Membership

Tests whether a list contains the specified item.

- id: no-new-privileges
assert: Containers should set no-new-privileges security option
severity: should
match:
path: services.*.security_opt
contains: "no-new-privileges:true"

not_value — Negated Exact Match

Tests that the value does not equal the specified value.

- id: no-privileged
assert: Containers must not run in privileged mode
severity: must
match:
path: services.*.privileged
not_value: true

exists — Presence/Absence Check

Tests whether a key exists (true) or does not exist (false).

- id: require-healthcheck
assert: All containers must have health checks configured
severity: must
match:
path: services.*.healthcheck
exists: true

Path Patterns

PatternMatches
services.web.imageExact path
services.*.image* matches one segment
**.containers.*.image** matches any depth

Assertions Without match

Omitting match makes an assertion LLM-context only. No values are stripped or annotated. Useful for standards requiring human judgment:

- id: resource-limits
assert: Production stacks should define resource limits
rationale: Prevents runaway containers from exhausting host resources
severity: should

Using decoct assertion learn

Derive assertions from standards documents, examples, or a corpus. Requires pip install decoct[llm] and ANTHROPIC_API_KEY.

Standards + examples

Terminal window
decoct assertion learn -s standards.md -e docker-compose.yml -o assertions.yaml

Corpus analysis

Analyse cross-file patterns to discover implicit standards:

Terminal window
decoct assertion learn \
-c configs/service-a.yml \
-c configs/service-b.yml \
-c configs/service-c.yml \
-p docker-compose \
-o learned-standards.yaml

Merging

Terminal window
decoct assertion learn -s updated-standards.md -m existing.yaml -o existing.yaml

Deduplicates by ID. Updated assertions (same ID, different content) are replaced.

Testing Assertions

Terminal window
# See compressed output with assertion effects
decoct compress config.yaml --assertions my-assertions.yaml
# See what was removed/annotated
decoct compress config.yaml --assertions my-assertions.yaml --show-removed
# Token statistics
decoct compress config.yaml --assertions my-assertions.yaml --stats

Writing Tips

  • IDs: Use lowercase, hyphenated, descriptive identifiers (e.g. require-healthcheck, no-privileged)
  • assert text: State what should be true, not what should not
  • rationale: Explain why, not just what
  • Severity: Use must for hard requirements, should for best practices, may for informational