Skip to content

Validation and linting

This page describes selected commands from the pinned APEX product. Run them in that checkout, not apex-docs. The current package.json, hook configuration, and CI files determine exact coverage.

The owner retired APEX .github/hooks/ runtime hooks in the October 18 migration. Do not restore them or introduce replacement hooks to satisfy an older validation recipe. validate:hooks and test:hooks below are historical pinned commands, not current setup requirements. Source-caller retirement belongs to the product change and is not verified by this docs update. Git Lefthook, pre-commit checks, secret scanning, other validators, and CI remain separate. See the retirement record for the lost protection and permission limits.

For this documentation site, use npm run build, npm run check:links, npm test, and npm run test:browser. The build uses the Linux toolchain and prepared pinned product metadata. The link checker validates routes and fragments. Use npm run check:external-links separately for external destinations.

Jump to: Architecture · Lefthook Hooks · Validation Scripts · CI Workflows · Running Locally

CodeGen proceeds in dependency-ordered batches of up to three new source files, with focused validation after each edit and a root check at each batch boundary. Routine next-file permission is not required. Explicit user stop requests, unresolved errors, ownership changes and human approval gates still stop progression.

Use these read-only commands from the repository root:

Terminal window
node tools/scripts/resolve-deployment-inputs.mjs --input approved-discovery-snapshot.json
node tools/scripts/validate-iac-handoff.mjs --tree-hash infra/bicep/example
node tools/scripts/summarize-deployment-preview.mjs --input preview.json --tool bicep --expected-ids expected.json
node tools/scripts/validate-policy-precheck.mjs precheck.json --preview preview.json --expected-ids expected.json
node tools/scripts/validate-provider-payload.mjs --input resolved-resources.json --s2-max-bytes 268435456000

The input resolver consumes approved values and read-only discovery snapshots; it performs no Azure calls or identity mutations. Its default report omits resolved values. See the input snapshot contract. An unset environment variable is not a reason to ask again for an already approved value.

Capture Bicep what-if with --no-pretty-print --output json. The summarizer returns exit 0 for checked evidence, 2 for required review and 1 for invalid or blocked evidence. Expected IDs come from approved resource bindings, including child resources, not from copying the observed result. A passing preview never grants apply permission.

For unexpected Bicep Ignore records only, both preview commands support --ignored-evidence bundle/ignored.json. The ignored-resource evidence contract binds exact preview/expected-ID hashes to saved parent/child observations. It supports private-endpoint NICs, SQL master and Storage-linked system topics, with exact IDs and reasons, not wildcard exclusions. The records remain visible in the summary. Changed actions, missing managed resources and unknown coverage still block; relationship evidence does not confer apply approval.

Provider-payload checks cover known SQL S2 and App Service Plan regressions only. Supply a concrete resource array extracted from generated payloads with recorded provenance; unresolved expressions remain unverified. The example SQL byte size must be checked against the target region’s capabilities and approved configuration before use. Compilation, provider validation, preview and successful deployment are distinct outcomes.

Validation runs at three stages, catching issues progressively earlier:

flowchart LR
    A["Pre-Commit<br/>(lefthook)"] --> B["Pre-Push<br/>(lefthook)"]
    B --> C["CI<br/>(GitHub Actions)"]
    style A fill:#e8f5e9,stroke:#4caf50,color:#000
    style B fill:#fff3e0,stroke:#ff9800,color:#000
    style C fill:#ffebee,stroke:#f44336,color:#000
  1. Pre-commit runs configured checks. Publication Markdown/artifact checks use the staged index.
  2. Pre-push selects domain checks for changed files.
  3. CI runs the suites and filters declared by the current workflow.

The Git hooks listed here are defined in lefthook.yml at the repository root.

Markdown and artifact checks run through node tools/scripts/check-publication-scope.mjs markdown|artifacts. They materialize an isolated index snapshot, so partially staged files are checked as committed. Unrelated untracked projects cannot block publication. Template, artifact-guidance and validator changes still run H2/template and review presence checks across all tracked artifacts in that snapshot. Markdown uses the installed local executable; failures propagate without filtering away exit codes. These checks never format, stage or rewrite project files.

HookTrigger (glob)Purpose
markdown-lint*.mdmarkdownlint on staged markdown files
artifact-validationStaged artifacts, templates, guidance and validatorsH2/template and review presence checks on tracked snapshot
agents**/*.agent.md, **/*.prompt.mdAgent frontmatter, model alignment, body size
instructions**/*.instructions.md, agents, skillsInstruction frontmatter and cross-reference validity
secrets-baseline(all staged files)gitleaks secret scan (soft-skip if not installed)
python-linttools/mcp-servers/**/*.pyRuff linter on Python files
terraform-fmt*.tfTerraform formatting check
terraform-validate*.tfTerraform validation per project
iac-security-baselineinfra/bicep/**/*.bicep, infra/terraform/**/*.tfTLS 1.2, HTTPS-only, no public blob, managed identity
HookPurpose
commitlintEnforce Conventional Commits format
HookPurpose
branch-namingValidate branch name uses an approved prefix
branch-scopeValidate domain branches only modify in-scope files
diff-based-checkRun domain-scoped validators for changed file types

All scripts are in the tools/scripts/ directory. Run via npm run <command>.

npm CommandScriptPurpose
validate:agentsvalidate-agents.mjsAgent frontmatter, body size, model alignment
validate:skillsvalidate-skills.mjsSkill format, affinity, references, stale refs
validate:skill-checksvalidate-skill-checks.mjsSkill size (≤500 lines) and references
validate:instruction-checksvalidate-instruction-checks.mjsInstruction frontmatter and applyTo patterns
validate:agent-registryvalidate-agent-registry.mjsAgent registry consistency
validate:workflow-graphvalidate-workflow-graph.mjsDAG integrity (no orphans, no cycles)
npm CommandScriptPurpose
validate:artifactsvalidate-artifacts.mjsH2 sync, template compliance, and auto-fix (with --fix)
npm CommandScriptPurpose
lint:governance-refsvalidate-governance-refs.mjsGovernance guardrails integrity
validate:no-hardcoded-countsvalidate-no-hardcoded-counts.mjsPrevent hardcoded entity counts
lint:deprecated-refsvalidate-no-deprecated-refs.mjsBlock deprecated API/pattern references
validate:iac-security-baselinevalidate-iac-security-baseline.mjsIaC security baseline (TLS, HTTPS, blob, identity, SQL auth)
npm CommandScriptPurpose
validate:session-statevalidate-session-state.mjsSchema validation + deprecated lock/claim field detection
validate:challenger-presencevalidate-challenger-presence.mjsRequired review findings exist for each review-mandated step; for projects with Step 2 complete, no *.tmp.md or FAILED cost files remain at the top level
validate:challenger-findingsvalidate-challenger-findings.mjsReview findings schema and freshness; rejects mutable parent-owned files (sku-manifest.json, 00-handoff.md, README.md, recall state, *-decisions.json) as supporting inputs
npm CommandScriptPurpose
lint:glob-auditvalidate-glob-audit.mjsDetect overly broad glob patterns
lint:orphaned-contentvalidate-orphaned-content.mjsDetect unreferenced skills/content
lint:docs-freshnesscheck-docs-freshness.mjsDocumentation staleness detection
validate:retirement-scanaudit-retirement-candidates.mjsTracked-file census and schema checks
lint:version-syncvalidate-version-sync.mjsVersion consistency across files
npm CommandScriptPurpose
validate:vscodevalidate-vscode-config.mjsVS Code settings completeness
validate:hooksvalidate-hooks.mjsHistorical runtime-hook check; not a setup requirement after retirement
test:hookstest-hooks.shHistorical runtime-hook tests; do not recreate deleted hooks to run them
lint:mcp-configvalidate-mcp-config.mjsMCP server configuration validity
npm CommandToolPurpose
lint:mdmarkdownlint-cli2Markdown formatting and style
format:checkPrettierCode formatting (JS/JSON/CSS; markdown via markdownlint)
lint:linkscheck-repository-links.mjsProduct repository link checks
lint:jsonlint-json.mjsJSON/JSONC syntax validation
lint:pythonruffPython code quality (tools/apex-recall/)
lint:terraform-fmtterraform fmtTerraform formatting compliance
lint:bicep-fmtbicep formatBicep formatting compliance (no-op when no projects)
validate:terraformterraform validateTerraform validation per project
npm CommandPurpose
validate:allRun cache-aware Node validators plus external validators
validate:_nodeNode validators in one cache-sharing process; bounded children for Python, ESLint, and tests
validate:_externalAll external tool validators in parallel
validate:agentsAgent frontmatter, body, model alignment
validate:artifactsH2 sync, template compliance, auto-fix
validate:skillsSkill format, affinity, references, stale
audit:quarterlyQuarterly context audit checks
audit:retirementGenerate or inspect the whole-repository retirement census

validate:_external is a local-developer aggregate (run all external-tool linters in one shot). In CI its members are gated individually so coverage does not depend on the aggregate: lint:md and format:check run in ci.yml, lint:python runs in the ci.yml external-tests job. Inspect current workflow steps for the remaining external checks; do not assume a retired iac-checks.yml still runs them. Site checks belong to the separate apex-docs repository.

validate:_node:legacy and validate:_node-ci:legacy retain the former unbounded run-p aggregates as rollback and benchmark baselines.

Agent-invoked IaC validators (runtime, not CI)

Section titled “Agent-invoked IaC validators (runtime, not CI)”

These validators are run by agents during the workflow against generated artifacts (Steps 4–6), not by lefthook or CI. They have no committed inputs on main, so they are intentionally absent from the aggregates above.

npm CommandInvoked byValidates
validate:iac-contract05-IaC Planner04-iac-contract.json schema/DAG
validate:iac-contract-consistency05-IaC PlannerContract ↔ implementation plan
validate:iac-handoff06b/06t CodeGen05-iac-handoff.json + tree hash
validate:environment-manifest05-IaC Planner04-environment-manifest.json
validate:policy-property-map05-IaC Planner04-policy-property-map.json
sync:draft-contract-hashes05-IaC PlannerRefreshes plan_ref and l1m_ref digests of an unapproved draft contract; keeps formatting; --write replaces the file atomically
  • validate:iac-contract --readiness --stage deploy|post-deploy|go-live (default deploy) fails an unresolved required capability only when its optional blocks list includes that stage or an earlier one. Without blocks a capability blocks every stage.
  • A phase or deployment_phase parameter may not declare a default.
  • Resources may declare phase, consumes (resources reached over a private path) and, on private endpoints, target. A depends_on into a later phase fails, and a consumer must depends_on a private endpoint that targets what it consumes. Contracts without these fields are not checked.
  • validate:iac-contract-consistency requires every resource without an AVM module entry to appear in the plan’s ### Raw Resource Exceptions section when that section exists.
  • validate:policy-property-map accepts status per policy: satisfied, pending, not-applicable (needs not_applicable_reason) and unsatisfiable (fails).

All workflows are in .github/workflows/.

This table describes the pinned product configuration, not proof that migration callers have been retired. Its historical runtime-hook checks do not authorize hook restoration or disabling unrelated CI.

WorkflowFileTriggerPurpose
CIci.ymlPR to main, push to mainFull validation suite (markdown, Prettier, agents, skills, hooks, bats tests, MCP, VS Code config) + Python ruff in the external-tests job
Branch Enforcementbranch-enforcement.ymlPR to mainBranch naming convention and scope validation
Consumer Template Checksconsumer-template-checks.ymlConfigured template checksValidate consumer-template behavior
Dev Container Base Validationvalidate-devcontainer-base.ymlRelevant PR changes or manual dispatchCompare candidate container bases on native architectures
Upstream Skill Driftupstream-skill-drift.ymlWeekly (Monday 06:00 UTC) or manual dispatchCompare the reviewed microsoft/azure-skills tag with the latest release (npm run report:upstream-skills) and keep one labelled issue up to date; never edits skills

The apex-docs repository owns the site’s build and publishing workflows. Product validation does not publish documentation.

Terminal window
# Run everything
npm run validate:all
# Run a specific category
npm run lint:md # Markdown only
npm run validate:agents # Agent definitions only
npm run validate:session-state # Session state only
# Auto-fix where supported
npm run lint:md:fix # Fix markdown issues
npm run fix:artifacts -- <file> --apply # Fix artifact H2 headings
npm run lint:python:fix # Fix Python lint issues