Skip to main content

In this article

Validation Commands and CI-Owned Lanes

Validation command names distinguish the checks that are safe defaults for a local development loop from lanes owned by CI. The distinction helps people and automation choose an appropriate default without implying that a CI-owned command cannot run on a workstation.

ci:* is a naming and default-agent-routing convention. It does not prevent local execution, add a runtime guard, or require a special npm flag. Run a named lane directly with its ordinary npm command when its prerequisites are available.

Start with local-safe validation

Use the smallest local-safe command that covers the change. Generic validation does not select a ci:* lane, and a command mentioned in documentation, a plan, a log, or an error message is not an agent execution request.

NeedCommandNotes
Repository-wide local-safe validationnpm run validate:localNon-mutating default validation aggregate
Documentation static and component checksnpm run validate:docsDoes not run the browser E2E lane
Markdown tables checknpm run lint:tablesNon-mutating table alignment check
Markdown link checknpm run lint:md-linksNon-mutating link check included in validate:local
Markdown tables fixnpm run format:tablesExplicitly mutates table formatting
Markdown lint fixnpm run lint:md:fixExplicitly mutates Markdown where possible
Targeted checknpm run <local-check>Choose the check that owns the changed file
Design Intent contract lintnpm run lint:design-intentValidates authored records and verification artifacts

For example, use npm run lint:md -- docs/contributing/validation.md for a targeted Markdown check, or invoke npm run lint:frontmatter after changing frontmatter. Use explicit fixers only when you intend to modify files, then review the resulting diff.

Install dependencies at the package root

This repository has independent lockfiles and package roots. Run npm ci in the root whose command you intend to use. Do not substitute npm install for the reproducible bootstrap path.

Package rootUse it for
Repository rootRoot validation, scripts, and ci:eval:* commands
docs/docusaurusDocusaurus lint, component test, build, and Playwright commands

Installing dependencies for one root does not provision the other roots. The root commands that delegate to Docusaurus still need the Docusaurus package dependencies available.

Install behind a restricted network

Some organizations block direct access to public package registries, release downloads, or gallery endpoints and require installs to route through approved proxies. Restore commands can then fail to reach npm or Python package indexes, commonly with ENOTCONN or a connection timeout. DevContainer setup can also fail while downloading tools or PowerShell modules.

This repository commits a project-level .npmrc that pins the canonical public registry, and npm resolves configuration in the order cli > env > project .npmrc > user .npmrc > global. A user-level ~/.npmrc is therefore outranked and silently ignored. Set an environment variable or pass a CLI flag instead.

Keep the proxy address out of the repository. It belongs in your own environment, never in a tracked file.

Each tool reads its own environment variable:

ToolEnvironment variablePublic default
npmnpm_config_registryhttps://registry.npmjs.org/
pipPIP_INDEX_URLhttps://pypi.org/simple/
uvUV_DEFAULT_INDEXhttps://pypi.org/simple/
EnvironmentWhere the override belongs
macOS or LinuxA file in your home directory sourced from ~/.zshrc or ~/.bashrc
WindowsA PowerShell profile ($PROFILE) or a user environment variable
Dev container or CodespaceHost environment before container creation; containerEnv for runtime package indexes only

macOS and Linux:

export npm_config_registry="https://proxy.example.com/npm/"
export PIP_INDEX_URL="https://proxy.example.com/pypi/simple/"
export UV_DEFAULT_INDEX="https://proxy.example.com/pypi/simple/"
npm ci

Windows PowerShell:

$env:npm_config_registry = 'https://proxy.example.com/npm/'
$env:PIP_INDEX_URL = 'https://proxy.example.com/pypi/simple/'
$env:UV_DEFAULT_INDEX = 'https://proxy.example.com/pypi/simple/'
npm ci

Dev container runtime package indexes, in VS Code user settings so no repository file changes:

{
"dev.containers.containerEnv": {
"NPM_CONFIG_REGISTRY": "https://proxy.example.com/npm/",
"PIP_INDEX_URL": "https://proxy.example.com/pypi/simple/",
"UV_DEFAULT_INDEX": "https://proxy.example.com/pypi/simple/"
}
}

DevContainer build and setup overrides

The repository DevContainer supports additional host-side overrides for container creation and setup. .devcontainer/devcontainer.json reads these values through ${localEnv:...}, so define them before opening VS Code or rebuilding the container.

VariablePurpose
HVE_DEVCONTAINER_IMAGESelects the base image used by the Dockerfile
NPM_CONFIG_REGISTRYSets the npm registry in the built container
PIP_INDEX_URLSets the pip-compatible Python package index
UV_DEFAULT_INDEXSets the Python package index used by uv
HVE_GITHUB_RELEASES_URLRedirects release binary downloads used by setup scripts
HVE_GITHUB_API_URLRedirects GitHub API requests made by security scripts
HVE_PSGALLERY_REPOSITORYSelects the PowerShell repository used for module installs
HVE_PSGALLERY_SOURCE_URLRegisters a custom PowerShell repository source URL

macOS and Linux:

export HVE_DEVCONTAINER_IMAGE="registry.corp.example.com/devcontainers/base:2-jammy"
export NPM_CONFIG_REGISTRY="https://proxy.example.com/npm/"
export PIP_INDEX_URL="https://proxy.example.com/pypi/simple/"
export UV_DEFAULT_INDEX="https://proxy.example.com/pypi/simple/"
export HVE_GITHUB_RELEASES_URL="https://artifacts.corp.example.com/github-releases"
export HVE_GITHUB_API_URL="https://github.corp.example.com/api/v3"
export HVE_PSGALLERY_REPOSITORY="InternalGallery"
export HVE_PSGALLERY_SOURCE_URL="https://packages.corp.example.com/powershell/"

Windows PowerShell:

$env:HVE_DEVCONTAINER_IMAGE = 'registry.corp.example.com/devcontainers/base:2-jammy'
$env:NPM_CONFIG_REGISTRY = 'https://proxy.example.com/npm/'
$env:PIP_INDEX_URL = 'https://proxy.example.com/pypi/simple/'
$env:UV_DEFAULT_INDEX = 'https://proxy.example.com/pypi/simple/'
$env:HVE_GITHUB_RELEASES_URL = 'https://artifacts.corp.example.com/github-releases'
$env:HVE_GITHUB_API_URL = 'https://github.corp.example.com/api/v3'
$env:HVE_PSGALLERY_REPOSITORY = 'InternalGallery'
$env:HVE_PSGALLERY_SOURCE_URL = 'https://packages.corp.example.com/powershell/'

Restart VS Code from the configured shell and run Dev Containers: Rebuild Container. Runtime containerEnv settings cannot change the base image because Docker resolves it before the container starts. See Enterprise artifact hub for the complete defaults, affected files, and security considerations.

Codespaces

For GitHub Codespaces, create account-specific development environment secrets named NPM_CONFIG_REGISTRY, PIP_INDEX_URL, and UV_DEFAULT_INDEX. These values become environment variables when the codespace is created or restarted; they do not configure the Docker image build.

onCreateCommand and updateContentCommand can run while a Codespaces prebuild is created, before account-specific secrets are available. Run setup that requires those secrets from postCreateCommand or later.

The committed .npmrc sets replace-registry-host=always, so npm rewrites each lockfile tarball host to the configured registry at fetch time only. npm ci never writes package-lock.json, and it still verifies every download against the committed sha512 integrity value.

Use restore commands for proxied installs. npm ci verifies downloads against the committed integrity values, and uv sync --frozen installs without updating the lockfile. A plain pip install -r verifies committed hashes only when the requirements file contains hashes and hash-checking mode is enabled, for example with --require-hashes. Dependency-resolution commands may update lockfiles with proxy-specific metadata. Review lockfile changes before committing, and run npm run lint:public-dependency-feeds if you suspect a lockfile picked up a non-public source.

Add or update a dependency from a restricted network

Generate the lockfile where the public registry is reachable, then commit the result. Dependabot covers version bumps of dependencies that already exist, but it does not add new ones.

SituationHow to produce the lockfile
Bump an existing dependencyLet Dependabot open the pull request
Add a new dependencyEdit package.json, push the branch, and let an agent or CI job run npm install
Need an interactive environmentUse a codespace or any workstation with direct public registry access

If a proxy-generated lockfile changes source or integrity metadata, regenerate it where the public registry is reachable instead of editing it by hand.

Documentation checks and browser lane

The documentation commands separate static and component validation from the browser-backed lane.

LaneCommandPrerequisites and costOutput and interpretation
Local docs validationnpm run validate:docsDocusaurus package dependencies. Fast local static and component work.Console output; use as the normal docs default
Docs browser setupnpm run ci:docs:setup:e2eDocusaurus dependencies, browser installation, and supported host privileges.Provisions Chrome for the E2E lane
Docs browser E2Enpm run ci:docs:test:e2eDocusaurus dependencies and Chrome. Browser-backed and potentially slower.docs/docusaurus/test-results/ and Playwright output show browser failures
Nested browser E2Enpm run ci:test:e2eRun from docs/docusaurus; same browser prerequisites.Standard browser-suite output
Nested fast or interactive modenpm run ci:test:e2e:fast or npm run ci:test:e2e:uiRun from docs/docusaurus; :ui is interactive.Use only when the relevant browser workflow is intended

The setup command and the E2E command remain separate. A generic validation request does not install a browser, start a service, or run Playwright. In hosted CI, a failed browser lane means the configured browser environment did not complete the suite. Locally, first determine whether the browser and its dependencies were provisioned before treating a launch failure as a product failure.

Evaluation lanes

Evaluation lanes are CI-owned because their prerequisites and costs vary. They remain directly runnable on a prepared local environment.

Static checks

These lanes do not invoke a model. They are suitable for deliberate local reproduction after installing root dependencies, but they are not included in validate:local.

LaneCommandTypical prerequisites and output
Eval spec and generator driftnpm run ci:eval:lint:vallyRoot dependencies and Vally; may write a drift diff under logs/
Eval schemanpm run ci:eval:lint:schemaRoot dependencies and PowerShell modules; writes schema results under logs/
Eval textnpm run ci:eval:lint:textRoot dependencies and Node; writes text-lint results under logs/
Eval safetynpm run ci:eval:lint:safetyRoot dependencies; writes logs/vally-test-safety.json
Skill hygienenpm run ci:eval:lint:skillsRoot dependencies and Vally; validates .github/skills/

Manifest, presence, and runtime sequence

Presence and execution lanes consume changed-artifact manifests. Generate the manifest with the existing script before invoking them locally, then retain the output in logs/ while diagnosing a failure.

LaneCommandPrerequisites, cost, and output
Stimulus presencenpm run ci:eval:presenceChanged-artifact manifest at logs/changed-ai-artifacts.json; fast structural check writing logs/stimulus-presence.json
Eval executionnpm run ci:eval:executeManifest, Vally, Copilot credential, and a noninteractive service-capable environment; model-backed and potentially costly; writes logs/eval-summary.json and per-spec results
General eval suitesnpm run ci:eval:runVally and model access; model-backed and potentially costly
One suitenpm run ci:eval:run:skills, npm run ci:eval:run:agents, or npm run ci:eval:run:scriptsSame model and service prerequisites as the selected suite
Agent conformancenpm run ci:eval:run:conformanceVally and model access; runs the six planner-agent conformance suites in sequence and stops at the first failing suite
Result comparisonnpm run ci:eval:compareExisting Vally result sets; compares prior outputs without selecting another suite
Prompt behaviornpm run ci:eval:behavior-promptsVally and model access; runs the prompt conformance spec
Instruction behaviornpm run ci:eval:behavior-instructionsVally and model access; runs the instruction conformance spec
Skill behaviornpm run ci:eval:behavior-skillsVally and model access; runs the skill behavior conformance spec
Agent matrix entrynpm run ci:eval:agentAgent-matrix arguments supplied after --; model-backed when execution is selected

Set COPILOT_GITHUB_TOKEN only in the environment that needs model-backed execution. Never commit credentials, paste them into documentation, or assume they are available to fork pull requests. Hosted CI clean-skips model execution when secrets are unavailable to an untrusted fork. A local credential or service failure is an environment result, not evidence that an eval contract failed.

Moderation

LaneCommandPrerequisites and output
Input moderationnpm run ci:eval:moderateRoot dependencies plus the moderation Python environment
Corpus moderationnpm run ci:eval:moderate:corpusChanged-artifact manifest and moderation Python environment
Artifact moderationnpm run ci:eval:moderate:artifactsChanged-artifact manifest and moderation Python environment; writes logs/moderation-artifacts.json
Moderation wrapper testsnpm run ci:eval:moderate:testRoot test dependencies; no model invocation

Provision the moderation environment with its locked uv environment in scripts/evals/moderation before running a real Detoxify lane. The model-backed moderation path can download or use model weights and is not a generic local validation default. A setup exit indicates missing dependencies rather than a clean moderation result.

Baseline equivalence and agent matrix

LaneCommandBehavior and output
Baseline equivalencenpm run ci:eval:equivalence -- -Agent rpi-agent -Tier prModel-backed comparison; writes logs/baseline-equivalence-summary.json and result trajectories under evals/results/
Equivalence dry runnpm run ci:eval:equivalence -- -Agent rpi-agent -WhatIfPrints planned work and writes a dry-run summary without SDK calls
Raw equivalence specsnpm run ci:eval:run:equivalenceRuns paired specs directly; requires the selected model environment
Agent matrixnpm run ci:eval:agent:matrixModel-backed nightly matrix; writes date-scoped output under evals/results/agent-matrix/
Agent matrix dry runnpm run ci:eval:agent:matrix:dryrunNo model invocation; writes a dry-run matrix summary
Changed-agent matrixnpm run ci:eval:agent:changedRequires a suitable git comparison base and model access

PR-tier equivalence results can be advisory while nightly results can be authoritative. Read the lane's generated JSON verdict and the hosted workflow status together. Do not infer a hosted CI policy from a direct local invocation.

Dashboards and reports

Dashboard generation is noninteractive. These commands generate artifacts but do not open a browser:

npm run ci:eval:agent:dashboard
npm run ci:eval:agent:report
npm run ci:eval:agent:report:dryrun
npm run ci:eval:dashboard

Only npm run ci:eval:agent:dashboard:open is interactive and opens the generated dashboard. Keep it separate from unattended validation or report generation.

Agent conformance workflow

Agent conformance is a CI-owned workflow that runs the six planner-agent suites under evals/agent-conformance/. It is invoked from weekly-validation.yml through workflow_call, has a 30-minute timeout, and requires the copilot-github-token secret exported as COPILOT_GITHUB_TOKEN. The workflow runs one matrix leg per suite with fail-fast: false, so a single failing agent does not mask the others:

npx vally eval --suite agent-conformance-dt-coach

Results are written under evals/results/ and uploaded as a per-suite artifact. Each stimulus launches the agent artifact in turn 0 and delivers the case query in turn 1, then grades the response with a model judge plus advisory wall-time and content budgets. Establish the credential through an operator-managed environment before a deliberate local reproduction. Do not ask for or transmit the credential through chat, do not treat this lane as part of validate:local, and do not infer its prerequisites from generic validation.

Review and cleanup

Review generated results before removing them. Common local outputs include logs/, evals/results/, docs/docusaurus/build/, and browser test-report directories. These artifacts help distinguish a contract failure from missing dependencies, unavailable credentials, or an unsupported local host.

Treat a passing local reproduction as useful evidence, not as a replacement for the hosted CI status. Hosted CI controls its own operating system, credentials, browser provisioning, and branch-protection policy.

🤖 Crafted with precision by ✨Copilot following brilliant human instruction, then carefully refined by our team of discerning human reviewers.