Skip to content

Policy Packs

Policy packs are versioned YAML files that define the rules your code is evaluated against. They live in .certification/policies/.

name: go-standard
version: "1.1.0"
language: go # optional — targets specific language
rules:
- id: go-vet-clean
dimension: correctness
description: "go vet must report zero issues"
severity: error
metric: lint_errors
threshold: 0
- id: low-complexity
dimension: maintainability
description: "Cyclomatic complexity under 15"
severity: warning
metric: cyclomatic_complexity
threshold: 15
- id: no-todos
dimension: readability
description: "No TODO/FIXME markers in production code"
severity: warning
metric: todo_count
threshold: 0
exclude_patterns:
- "*_test.go"
FieldRequiredDescription
nameYesUnique policy pack name
versionYesSemantic version string
languageNoTarget language (go, ts, py). Omit for universal.
path_patternsNoGlob patterns — only apply this pack to matching paths
FieldRequiredDescription
idYesUnique rule identifier
dimensionYesQuality dimension this rule evaluates
descriptionYesHuman-readable explanation
severityYeserror (must pass) or warning (observation)
metricYesEvidence metric to check
thresholdYesMaximum acceptable value
path_patternsNoGlob patterns — only apply this rule to matching paths
exclude_patternsNoGlob patterns — skip this rule for matching paths

Rules and entire packs can be scoped to specific paths using glob patterns.

Apply a rule only to specific paths:

rules:
- id: no-panic
dimension: security
description: "Library code should not call panic()"
severity: error
metric: panic_calls
threshold: 0
path_patterns:
- "internal/**"
exclude_patterns:
- "*_test.go"

This rule applies only to files under internal/ and skips test files.

Scope an entire policy pack to a path:

name: go-library
version: "1.0.0"
language: go
path_patterns:
- "internal/**"
rules:
- id: no-panic
# ...
- id: no-os-exit
# ...
# Only apply to non-test production code
exclude_patterns:
- "*_test.go"
- "testdata/**"
# Only apply to internal library code
path_patterns:
- "internal/**"
- "pkg/**"
# Only apply to CLI entry points
path_patterns:
- "cmd/**"
MetricSourceDescription
lint_errorsLinter outputNumber of lint errors
test_failuresTest runnerNumber of failing tests
todo_countCode scanTODO/FIXME comment count
code_linesCode metricsLines of code
complexityCode metricsCyclomatic complexity

Structural (AST analysis — all languages with analyzer)

Section titled “Structural (AST analysis — all languages with analyzer)”
MetricSourceDescription
param_countASTNumber of function parameters
return_countASTNumber of return values
func_linesASTLines in function body
max_nesting_depthASTDeepest nesting level
has_doc_commentASTHas documentation comment
cognitive_complexityASTSonar-style cognitive complexity
errors_ignoredASTError returns assigned to _
errors_not_wrappedASTErrors returned without wrapping
naked_returnsASTBare return in named-return functions
panic_callsASTpanic(), throw, unwrap() calls
empty_catch_blocksASTcatch/except/recover with empty body
os_exit_callsASTos.Exit() / sys.exit() calls
defer_in_loopASTDefer/finally inside loops
method_countASTMethods on a type (type-level)
context_not_firstASTcontext.Context not first param (Go)
has_init_funcASTFile contains init()
global_mutable_countASTPackage-level mutable variables
unsafe_import_countASTDangerous imports (os/exec, eval, subprocess)
hardcoded_secretsASTString literals matching secret patterns
loop_nesting_depthASTMax nested loop depth
recursive_callsASTDirect recursive calls
nested_loop_pairsASTInner loops nested in outer loops
quadratic_patternsASTKnown O(n²) anti-patterns

Deep Analysis (type-aware — Go built-in, TS/Py/Rs via LSP)

Section titled “Deep Analysis (type-aware — Go built-in, TS/Py/Rs via LSP)”
MetricSourceDescription
fan_inCall graphNumber of call sites invoking this function
fan_outCall graphNumber of distinct functions called
is_dead_codeReferencesExported symbol with zero external references
dep_depthImport graphTransitive local import depth
instabilityImport graphCe/(Ca+Ce) — 0=stable, 1=unstable
concrete_depsType analysisParams accepting concrete external struct types
coupling_scoreCall graphfan_in × fan_out normalized
unused_paramsType analysisParameters never referenced in function body
interface_sizeType analysisMethods in interfaces this type implements
type_aware_unwrappedType analysisError returns without wrapping (type-verified)

Rules can target any of the 9 quality dimensions:

correctness, maintainability, readability, testability, security, architectural_fitness, operational_quality, performance_appropriateness, change_risk

SeverityEffect
errorFailing this rule blocks certification (unit is decertified)
warningCreates an observation but unit can still be certified

Policies with a language field only apply to units of that language:

language: go # Only applies to go:// units

Policies without a language field apply to all units.

certify init generates auto-detected policy packs:

  • go-standard.yml (v1.4.0) — 22 rules: lint clean, complexity, fan-in/fan-out limits, dead code, dep depth, cognitive complexity, unsafe imports, hardcoded secrets, error wrapping
  • go-library.yml — Library-specific rules scoped to internal/** (no panic, no os.Exit)
  • ts-standard.yml — TypeScript rules: complexity, nesting, empty catch, unsafe imports
  • python-standard.yml — Python rules: complexity, bare except, subprocess usage
  • rust-standard.yml — Rust rules: complexity, unwrap() usage, unsafe blocks

The split ensures os.Exit in CLI entry points and TODO strings in test fixtures don’t generate false observations.

Add any .yml file to .certification/policies/ — it’s automatically loaded on the next certification run. Policy packs are matched to units by language and path patterns.