Baseline CI checks
apm audit --ci runs a fixed set of baseline checks against the project on
disk. Baseline checks are always on – they need no apm-policy.yml. With
policy discovery active, the org policy contributes additional checks on
top (see apm policy and the
policy schema).
This page documents the baseline set defined in
src/apm_cli/policy/ci_checks.py. For the command surface, see
apm audit. For the CI wiring, see
Enforce in CI.
Exit-code contract
Section titled “Exit-code contract”| Outcome | Exit code |
|---|---|
| All baseline checks pass (and any policy + drift checks pass) | 0 |
| Any baseline, policy, or drift check fails | 1 |
--no-fail-fast runs every check before exiting; the default stops at the
first failure to skip expensive I/O.
At a glance
Section titled “At a glance”| ID | Severity | Source | Always on? |
|---|---|---|---|
manifest-parse |
block | ci_checks.py |
only when apm.yml cannot be parsed |
lockfile-exists |
block | ci_checks.py |
yes |
ref-consistency |
block | ci_checks.py |
yes |
deployment-ledger-owners |
block | ci_checks.py |
yes |
deployed-files-present |
block | ci_checks.py |
yes |
no-orphaned-packages |
block | ci_checks.py |
yes |
skill-subset-consistency |
block | ci_checks.py |
yes |
config-consistency |
block | ci_checks.py |
yes |
content-integrity |
block | ci_checks.py |
yes |
includes-consent |
advisory | ci_checks.py |
yes (advisory; promotable by policy) |
drift |
block | _check_drift in ci_checks.py, invoked from commands/audit.py |
yes, unless --no-drift |
Policy checks (dependency-allowlist, dependency-denylist,
required-packages, required-packages-deployed,
required-package-version, transitive-depth, and others in
policy/policy_checks.py) only run when an apm-policy.yml is resolved
through discovery or --policy. They are out of scope for this page; see
the policy schema.
Baseline checks
Section titled “Baseline checks”manifest-parse
Section titled “manifest-parse”- What it verifies. That
apm.yml, if present, is valid YAML and a valid APM manifest. - Fails when. The file exists but cannot be parsed (
yaml.YAMLError,ValueError, orOSError). - Effect. Skips every other check and exits
1. This is the only check that runs before the lockfile gate. - Remediation. Fix the YAML syntax error reported in the message and re-run.
lockfile-exists
Section titled “lockfile-exists”- What it verifies. That
apm.lock.yamlis present whenever the project has APM or MCP dependencies (includingdevDependencies), or whenever an existing lockfile records local content under the synthesized self-entry. - Fails when.
apm.ymldeclares dependencies (production or dev) but no lockfile is on disk. - Effect. Subsequent checks are skipped (the lockfile is required input).
- Remediation. Run
apm installto generateapm.lock.yamland commit it.
ref-consistency
Section titled “ref-consistency”- What it verifies. That every dependency’s
referenceinapm.yml(bothdependencies.apmanddevDependencies.apm) matches theresolved_refrecorded in the lockfile. - Fails when. A manifest ref differs from the lockfile entry, or the manifest declares a dependency that is missing from the lockfile.
- Remediation. Run the command the check message names:
apm install --updatewhen the lockfile already holds a resolution that must be refreshed or re-keyed (the source-identity rewrite and commit-pin mismatch cases), or plainapm installfor a first resolution – so the lockfile re-resolves to the manifest, then commitapm.lock.yaml. - Runs before
deployment-ledger-owners. This external manifest-versus-lockfile identity check is evaluated ahead of the internal ledger-owner check on purpose. A source-identity tamper (a rewritten dependencyhost/repo_urlin the lockfile) trips both, but onlyref-consistencypoints at the safe fix – re-resolving from the trusted manifest viaapm install --update. The ledger-owner remedy (apm prune) reconciles ownership toward the current lockfile, so it must never be the surfaced cause when the manifest and lockfile disagree about a dependency’s identity.
deployment-ledger-owners
Section titled “deployment-ledger-owners”- What it verifies. That every canonical
deploymentsrow’sownersandactive_ownerresolve to a member of the valid owner universe: a current key inapm.lock.yaml’sdependencies, the workspace self-owner., orlocal-bundle. - Fails when. A row references a dependency key that has since been
removed from the lockfile (a stale, “ghost” owner), or
active_owneritself is invalid. This is a hard integrity failure, distinct from ordinary drift – unlike hand-edits or missing files, it fails in both bareapm auditandapm audit --ci. - Effect. Findings render in text, JSON, SARIF, and markdown output
alike, naming the locator and its invalid owner(s).
apm audit --striprefuses to modify content while any reference is invalid. - Remediation. Run
apm prune, then rerunapm audit. Prune repairs the stale ownership metadata; it does not delete files based on a ghost row alone. Seeapm pruneand Lockfile spec.
deployed-files-present
Section titled “deployed-files-present”- What it verifies. That every path in each lockfile entry’s
deployed_filesexists on disk under the project root. Gitignored paths are considered expected-absent and do not cause a failure. - Fails when. One or more non-gitignored deployed files are missing (e.g. a developer ran
apm installthen deleted integrated files, or skipped install entirely). - Remediation. Run
apm installto restore integrated files. Whenapm.ymldeclares targets, install also removes stale entries outside the declared, gated, and dynamic target set. Then commit the updated lockfile:git add apm.lock.yaml && git commit.
no-orphaned-packages
Section titled “no-orphaned-packages”- What it verifies. That every dependency in the lockfile is still declared in
apm.yml(in eitherdependencies.apmordevDependencies.apm). The synthesized self-entry is excluded. - Fails when. The lockfile holds a package that the manifest no longer lists.
- Remediation. Run
apm installto prune the orphan, then commitapm.lock.yaml.
skill-subset-consistency
Section titled “skill-subset-consistency”- What it verifies. That each
skills:selection inapm.ymlmatches theskill_subsetrecorded in the lockfile, and that every recorded skill path exists in the resolved package tree. When CI audit has prepared a lock-pinned scratch replay, this check uses its dependency tree instead of checkout-localapm_modules/; no checkout install is required. - Fails when. The sorted manifest skill list differs from the sorted lockfile
skill_subset, or a recorded subset path does not map to a deployable skill in the dependency tree being checked. - Remediation. Run
apm installto regenerate the lockfile against the current selection.
config-consistency
Section titled “config-consistency”- What it verifies. That MCP server configs derived from the root
dependencies.mcpanddevDependencies.mcp, plusdependencies.mcpfrom every current local or installed-remote package manifest bounded by the lockfile, match themcp_configsbaseline. Dependency-packagedevDependencies.mcpis author-only and is excluded from the consumer baseline. - Fails when. A server’s resolved config differs from the lockfile, a server exists on only one side, or a locked package manifest is unreadable. In
apm audit --ci, whenapm_modules/is absent but the lockfile is present, APM first self-hydrates a lock-pinned scratch install and derives the current MCP truth from that isolated modules tree; if the scratch replay itself fails,config-consistencyfails closed with the replay error. A missing manifest also fails unless the lockfile records a skill bundle, or records a remote Claude skill at a repository root or subdirectory. Before remote materialization the locked type is authoritative; once materialized, the on-disk shape and lock metadata must both identify a Claude skill. Present local paths use the same shape-and-lock check, while a missing local path still fails.mcp_config_provenanceidentifies the package in lock-only diagnostics but never exempts a removed declaration. - Remediation. Run
apm installto reconcile the MCP configuration or restore an unreadable package source.
content-integrity
Section titled “content-integrity”- What it verifies. Two independent signals, including local
.apm/deployments recorded through the synthesized self-entry:- Critical hidden Unicode in recognized prompt documents and decoded native prompt fields. Discovery uses each resolved target’s filenames and primitive patterns, including untracked files and shared hook settings. Recorded paths use the same applicability rules: tracking a command or script does not turn it into prompt text. Hook definitions remain visible even when their command-only content is not applicable to Unicode prompt checks. Session transcripts, history, caches, command strings and referenced executables are not scanned. See Discovery and prompt coverage for the format boundaries.
- SHA-256 drift between the on-disk content and the hash recorded in
deployed_file_hashesat install time. Necessarily lockfile-scoped: an unrecorded file has no baseline to compare against.
- Fails when. An applicable prompt contains critical Unicode, recognized content is unreadable or unsupported (incomplete coverage), a recorded hash differs, or a legacy hash lacks canonical ownership metadata. Missing files are reported by
deployed-files-present; unrecorded files have no hash baseline. Existing path and symlink protections still apply. - Remediation. Review the reported format or access error for incomplete coverage. Use
apm audit --striponly for supported regular prompt documents; structured/shared settings and external-root findings require manual review. Runapm installto restore hash-drifted files. Discovery does not grant ownership or permission to rewrite user configuration.
includes-consent
Section titled “includes-consent”- What it verifies. That projects deploying local content (the lockfile’s
local_deployed_filesis non-empty) declare anincludes:field inapm.ymlfor explicit governance. - Fails when. Never – this check is advisory and always passes. The message advises adding
includes: auto(or an explicit list) when local content is deployed without a declaration. - Promote to a block. Set
manifest.require_explicit_includesinapm-policy.ymlto make missingincludes:fail the policy layer. - Remediation. Add
includes: autotoapm.yml, or list the paths explicitly.
- What it verifies. That the working tree matches what an install from the current lockfile would produce. The check replays the install pipeline into a scratch tree and diffs the result against the project.
- Fails when. Any deployed file differs from the replay output (hand-edits, missing integrations, orphaned files). For shared hook configuration files, the comparison covers only APM-owned hook entries; user-owned hooks are preserved and do not create drift. The complete APM-owned sidecar is compared as JSON, ignoring object-key order and formatting but preserving all fields and list order; changed content, malformed JSON, duplicate keys, and non-JSON constants (
NaN,Infinity,-Infinity) still fail. Inapm audit --ci, a cold cache no longer yields a green skip: ifapm_modules/is absent, APM self-hydrates a lock-pinned scratch install first and then diffs against the checkout. If that scratch replay cannot be materialized, the drift check fails closed with the replay error. - Skips when. Only in bare
apm audit, where the replay remains cache-only and a missing cache yields an informational skip advising the user to runapm installfirst. - Skip with.
apm audit --ci --no-drift(reduces coverage; reserve for performance-constrained CI loops). - Remediation. Run
apm installto restore the deployed state, or revert the hand-edit. For a cache-miss skip, the sameapm installwarms the cache and enables the check on the next run.
Run order and fail-fast
Section titled “Run order and fail-fast”The aggregate runner in run_baseline_checks evaluates checks in this order: manifest-parse (only when apm.yml is unparseable), lockfile-exists, ref-consistency, deployment-ledger-owners, deployed-files-present, no-orphaned-packages, skill-subset-consistency, config-consistency, content-integrity, includes-consent. Drift is invoked separately by the audit command after the baseline batch, but in --ci mode it shares the same cold-cache scratch materialization with skill-subset-consistency and config-consistency.
With fail-fast on (the default), the runner stops at the first failing check. apm audit --ci --no-fail-fast evaluates every check so the report lists every problem at once.
Related
Section titled “Related”apm audit– the command surface and modes.apm prune– reconcilesdeployment-ledger-ownersfindings.apm policy– inspect, validate, and resolve org policy.- Policy schema – the policy-gated checks layered on top of this baseline.
- Enforce in CI – wiring the gate into branch protection.