From an indicator to a command
Two real evidence recipes, read end to end: what the indicator asks, the commands that fetch the evidence, and the controls the output traces to — one from the cloud estate, one from the build pipeline.
An evidence recipe is the unit this whole site is built around: the claim, the commands that fetch the evidence for it, the output you should expect, and the controls that output traces to. Here are two real ones from the authored corpus, end to end — read each top to bottom before moving on. Note what the honesty rating on each one is doing: it is a verdict about the output, not about the effort.
AWS Config compliance result for the managed rule proving every IAM user with a console password has MFA enabled
fetch
$ aws configservice get-compliance-details-by-config-rule --config-rule-name mfa-enabled-for-iam-console-access --compliance-types NON_COMPLIANT$ aws configservice describe-configuration-recorder-status$ aws configservice describe-config-rule-evaluation-status --config-rule-names mfa-enabled-for-iam-console-accessExpected output: EvaluationResults array; empty NON_COMPLIANT set means all console-enabled IAM users have MFA. Managed rule identifier: MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS Plus describe-configuration-recorder-status showing recording=true and, per rule, describe-config-rule-evaluation-status showing FirstEvaluationStarted=true with a LastSuccessfulEvaluationTime — the proof the empty set was produced by a check that ran.
maps to: ia-2 · cadence: continuous · full recipe: /collect/config-mfa-enabled-console-access
One command, one question, and the output answers it — for the IAM users the rule can see, which is why the check is written as an assertion and the rating is still partial. The subtlety worth stealing: an empty result is the PASS condition here — which is only safe because the rule's existence and evaluation activity can be proven separately. Hold that thought for step 6.
Whether static analysis is configured in this organization and which repositories it actually reaches; for each of those repositories, which query suite ran over which languages, whether the recurring schedule is still alive, when the analysis last ran and with how many rules in the run; and what the analysis found, split into what is still open and what a person closed by hand — each closure carrying who closed it, which of four fixed reasons they chose, and whatever they wrote down. The first two halves are the population and the proof that testing happened; the third is the half an assessment asks for, and read without the other two it cannot be told apart from the output of a scanner that never ran.
fetch
$ gh api --paginate "/orgs/<ORG>/code-security/configurations"$ gh api --paginate "/orgs/<ORG>/code-security/configurations/<CONFIGURATION_ID>/repositories?per_page=100"$ gh api "/repos/<ORG>/<REPO>/code-scanning/default-setup"$ gh api --paginate "/repos/<ORG>/<REPO>/code-scanning/analyses?tool_name=CodeQL&ref=refs/heads/<DEFAULT_BRANCH>&per_page=100"$ gh api --paginate "/orgs/<ORG>/code-scanning/alerts?state=open&tool_name=CodeQL&per_page=100"$ gh api --paginate "/orgs/<ORG>/code-scanning/alerts?state=dismissed&tool_name=CodeQL&per_page=100"Expected output: Report names used below, and the command each comes from: `configurations` is the first command, `configuration-repositories` the second, `default-setup` the third, `analyses` the fourth, `alerts-open` the fifth and `alerts-dismissed` the sixth. RUN COMMANDS 3 AND 4 ONCE PER REPOSITORY, not once for the organization. There is no organization-scoped analyses endpoint and no organization-scoped default-setup endpoint — GitHub documents both only under /repos/{owner}/{repo} — while the alert endpoints exist at both scopes. So the population half of this recipe is assembled one repository at a time and the findings half arrives in one list, and collecting one repository's analyses and reading them as the organization's is the arithmetic error this recipe is most likely to be assessed with. From `configurations`, configuration objects whose code-scanning fields are `code_scanning_default_setup` and `code_scanning_delegated_alert_dismissal`, each documented as `enabled | disabled | not_set`, plus `code_scanning_default_setup_options` carrying `runner_type` (`standard | labeled | not_set`) and `runner_label`. Each row also carries `target_type`, which is `global | organization | enterprise` — and the list endpoint's own `target_type` parameter is documented `Default: all`, so THIS RESPONSE IS NOT A LIST OF CONFIGURATIONS THE ORGANIZATION AUTHORED. It can contain a GitHub-provided global configuration and an enterprise-owned one, neither of which the organization can edit, and both of which can be the thing that switched code scanning on. The two clauses below split on exactly that distinction; read their descriptions together rather than separately. From `configuration-repositories`, association rows whose `status` is one of `attached | attaching | detached | removed | enforced | failed | updating | removed_by_enterprise`; the call passes no `status` filter, whose documented default is `all`, which is deliberate here because the `failed` row is what one clause below exists to catch. From `default-setup`, `state` (`configured | not-configured`), `languages` drawn from `actions, c-cpp, csharp, go, java-kotlin, javascript-typescript, python, ruby, swift`, `query_suite` (`default | extended`), `threat_model` (`remote | remote_and_local`), `runner_type`, `runner_label`, `updated_at` and `schedule` (`weekly | null`). From `analyses`, analysis objects with `id`, `ref`, `commit_sha`, `analysis_key`, `environment`, `category`, `error`, `warning`, `created_at`, `results_count`, `rules_count`, `sarif_id`, `deletable` and a `tool` object of `name`, `version`, `guid`. `sort` accepts only `created` and `direction` defaults to `desc`, which is what makes `analyses[0]` the most recent run and is the documented behaviour the freshness clause depends on — a collector that overrides either has changed what that clause means. The command narrows on `ref` as well as `tool_name`, and both narrowings are load-bearing: without `ref` the newest row can be a pull-request analysis (`refs/pull/N/merge`), and GitHub documents `category` as what distinguishes "multiple analyses for the same tool and commit, but performed on different languages or different parts of the code", so on a multi-language repository `analyses[0]` is whichever LANGUAGE finished last. There is no server-side `category` filter, so a repository with more than one analysed language needs the freshness clause read per category — see the note. From both alert lists, alerts with `number`, `created_at`, `updated_at`, `state` (`open | dismissed | fixed | null`), `fixed_at`, `dismissed_by`, `dismissed_at`, `dismissed_reason` (`false positive | won't fix | used in tests | mitigated | null`), `dismissed_comment` (nullable, max 280 characters), a `rule` object (`id`, `name`, `severity` `none | note | warning | error`, `security_severity_level` `low | medium | high | critical`, `description`, `full_description`, `tags`, `help`, `help_uri`), a `tool` object, `most_recent_instance` (with `ref`, `analysis_key`, `category`, `commit_sha`, `location`, `classifications`) and, at organization scope, the `repository` the alert belongs to. Read the alert lists knowing two documented things about them: the organization endpoint takes no `ref` filter, and GitHub states that "The status and details on the alert page only reflect the state of the alert on the default branch of the repository, even if the alert exists in other branches" — so this is a default-branch picture, not a repository-wide one. Both alert commands pass `tool_name=CodeQL`, because code scanning stores third-party SARIF in the same store and this recipe's claims are about the CodeQL analyses the fourth command measures.
maps to: sa-11 · cadence: continuous · full recipe: /collect/static-analysis-coverage-and-flaw-disposition
Same shape, different plane, and an honest partial. The control it serves has several distinct limbs; these calls prove that analysis ran, where, and with which ruleset — and the recipe's own notes say plainly which limbs remain documents a human writes. That sentence is what partial means.
Every recipe in the corpus renders like this at /collect, and a printed one is an evidence-collection SOP. The next step takes the badge away and asks you to supply it.
Exit check — both recipes rate partial; what makes the first one’s check writable and the second one’s not, in one sentence each?
The first: the check is a written assertion over a named field, and the rating is partial only for the population the rule cannot see. The second: the output is probative but the control has limbs no platform API reaches, so a human still writes part of the evidence — and the recipe says which part.