Skip to content
Merged
9 changes: 9 additions & 0 deletions .github/instructions/workflows.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,14 @@ with:

Avoid `format()` workarounds or environment variable indirection when the simpler options above apply.

## PR Validation Gate

`pr-validation.yml` exposes a single `pr-validation-success` aggregator job as the required status check that gates merge. This job is green only when every other job in the workflow passes.

Every job defined in `pr-validation.yml`, except `pr-validation-success` itself, MUST appear in the `needs:` list of the `pr-validation-success` job. Omitting a job lets that job fail silently without blocking merge, which defeats the gate.

The `gate-completeness-check` job enforces this rule in CI, failing the workflow whenever the gate's `needs:` list drifts out of sync with the defined jobs. Contributors can validate the gate locally by running `npm run lint:pr-gate` before pushing.

## Enforcement Statement

The following scripts enforce compliance:
Expand All @@ -316,5 +324,6 @@ The following scripts enforce compliance:
* `scripts/security/Test-SHAStaleness.ps1` - Checks for stale dependencies
* `scripts/security/Test-WorkflowPermissions.ps1` - Validates workflow permissions declarations
* `scripts/linting/Invoke-YamlLint.ps1` - Runs actionlint validation
* `scripts/security/Test-PrValidationGate.ps1` - Validates the PR validation gate `needs:` completeness

All workflows must pass these validation checks to be merged into the repository.
20 changes: 10 additions & 10 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: GitHub Actions Workflows
description: Modular CI/CD workflow architecture for validation, security scanning, and automated maintenance
author: HVE Core Team
ms.date: 2026-05-01
ms.date: 2026-06-27
ms.topic: reference
keywords:
- github actions
Expand Down Expand Up @@ -47,14 +47,14 @@ Modular reusable workflows following Single Responsibility Principle. Each workf

Compose multiple reusable workflows for comprehensive validation and security scanning.

| Workflow | Triggers | Jobs | Mode | Purpose |
|-----------------------------------|-----------------------------------------|-----------------------------------------------------------------|----------------------------|--------------------------------------|
| `pr-validation.yml` | PR to main/develop (open, push, reopen) | 9 jobs (8 reusable workflows + 1 inline) | Strict validation | Pre-merge quality gate with security |
| `release-stable.yml` | Push to main | 5 jobs (5 reusable workflows) | Strict mode, SARIF uploads | Post-merge validation |
| `weekly-security-maintenance.yml` | Schedule (Sun 2AM UTC) | 4 (validate-pinning, check-staleness, codeql-analysis, summary) | Soft-fail warnings | Weekly security posture |
| `scorecard.yml` | Push to main, Schedule (Sun 3AM UTC) | 1 (scorecard) | SARIF upload | OpenSSF Scorecard security posture |
| Workflow | Triggers | Jobs | Mode | Purpose |
|-----------------------------------|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------|--------------------------------------|
| `pr-validation.yml` | PR to main/develop (open, push, reopen) | 31 jobs (29 validation jobs + `pr-validation-success` gate + `gate-completeness-check`); `pr-validation-success` is the merge signal | Strict validation | Pre-merge quality gate with security |
| `release-stable.yml` | Push to main | 5 jobs (5 reusable workflows) | Strict mode, SARIF uploads | Post-merge validation |
| `weekly-security-maintenance.yml` | Schedule (Sun 2AM UTC) | 4 (validate-pinning, check-staleness, codeql-analysis, summary) | Soft-fail warnings | Weekly security posture |
| `scorecard.yml` | Push to main, Schedule (Sun 3AM UTC) | 1 (scorecard) | SARIF upload | OpenSSF Scorecard security posture |

pr-validation.yml jobs: codeql-analysis, spell-check, markdown-lint, table-format, psscriptanalyzer, frontmatter-validation, link-lang-check, markdown-link-check, dependency-pinning-check
pr-validation.yml jobs: 29 validation jobs feed a single `pr-validation-success` aggregator gate, which is the only required status check that gates merge; a `gate-completeness-check` job verifies every validation job is wired into that gate's `needs:` list.

release-stable.yml jobs: spell-check, markdown-lint, table-format, codeql-analysis, dependency-pinning-scan

Expand Down Expand Up @@ -250,8 +250,8 @@ Workflow Execution Matrix:

| Event | Workflows That Run | CodeQL Included |
|--------------------------------------|----------------------------------------------------------|---------------------|
| Open PR to main/develop | `pr-validation.yml` (9 jobs) | ✅ Yes |
| Push to PR branch | `pr-validation.yml` (9 jobs) | ✅ Yes |
| Open PR to main/develop | `pr-validation.yml` (31 jobs) | ✅ Yes |
| Push to PR branch | `pr-validation.yml` (31 jobs) | ✅ Yes |
| Merge to main | `release-stable.yml` (5 jobs) | ✅ Yes |
| Sunday 4AM UTC | `codeql-analysis.yml`, `weekly-security-maintenance.yml` | ✅ Yes (standalone) |
| Feature branch push (no open PR)[^1] | None | ❌ No |
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/docusaurus-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ jobs:
Write-Output 'Docusaurus tests requested for all files.'
} else {
$baseRef = if ($env:GITHUB_BASE_REF) { $env:GITHUB_BASE_REF } else { 'main' }
# Trigger on Docusaurus application changes only: the site app, plugins,
# configs, and accessibility tests all live under docs/docusaurus/.
# Pure markdown content edits elsewhere under docs/ are intentionally
# excluded so content-only PRs skip the expensive a11y/build job.
# Trigger on any change under docs/: the whole-site build compiles all of
# docs/** (docusaurus.config.js sets the docs plugin path to '../', excluding
# only docusaurus/** and announcements/**), so watching docs/ matches the
# build's real input set. This catches broken links in markdown content
# pages on the PR instead of only on the post-merge deploy build.
# The collections/ tree is included because docusaurus.config.js reads
# collections/*.collection.yml at build time (collectionCounts) and the
# tests consume it via COLLECTIONS_DIR, so changes there alter site and
# test output. The workflow files themselves are included so test/config
# changes still trigger a run.
$changed = @(git diff --name-only --diff-filter=ACMR "origin/$baseRef...HEAD" -- `
docs/docusaurus `
docs `
collections `
.github/workflows/docusaurus-tests.yml `
.github/workflows/deploy-docs.yml)
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,73 @@ jobs:
security-events: write # Required for SARIF upload to Security tab
actions: read

gate-completeness-check:
name: PR Gate Completeness
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Setup PowerShell modules
uses: ./.github/actions/setup-ps-modules

- name: Validate PR gate completeness
shell: pwsh
run: ./scripts/security/Test-PrValidationGate.ps1 -FailOnViolation

pr-validation-success:
name: PR Validation Success
runs-on: ubuntu-latest
permissions:
contents: read
if: always()
needs:
- spell-check
- markdown-lint
- table-format
- psscriptanalyzer
- discover-python-projects
- python-lint
- copyright-headers
- yaml-lint
- pester-tests
- pytest
- fuzz-tests
- pip-audit
- docusaurus-tests
- frontmatter-validation
- adr-consistency-validation
- ai-artifact-validation
- msdate-freshness
- plugin-validation
- skill-validation
- eval-validation
- link-lang-check
- markdown-link-check
- dependency-pinning-check
- devcontainer-lockfile-check
- workflow-permissions-check
- action-version-consistency-scan
- gitleaks-scan
- npm-audit
- codeql
- gate-completeness-check
steps:
- name: Verify all jobs succeeded
env:
NEEDS_JSON: ${{ toJSON(needs) }}
shell: bash
run: |
set -euo pipefail
failed=$(echo "$NEEDS_JSON" | jq -r 'to_entries[] | select(.value.result != "success" and .value.result != "skipped") | .key')
if [ -n "$failed" ]; then
echo "The following jobs did not pass:"
echo "$failed"
exit 1
fi
echo "All PR validation jobs passed."

20 changes: 10 additions & 10 deletions docs/agents/project-planning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ These agents bring structure and consistency to activities that teams often hand

## Agent Overview

| Agent | Sub-Category | Workflow | Persistence | Key Output |
|----------------------------------------|--------------|-----------------------------|-------------|--------------------------------|
| [BRD Builder](brd-prd-builders) | Requirements | 3-phase Q&A | JSON state | Business requirements document |
| [PRD Builder](brd-prd-builders) | Requirements | 7-phase Q&A | JSON state | Product requirements document |
| [ADR Creator](adr-creation) | Architecture | 3-phase Frame/Decide/Govern | JSON state | Architecture decision record |
| [Security Planner](../security/README) | Security | 6-phase STRIDE | JSON state | Security model and backlog |
| Agent | Sub-Category | Workflow | Persistence | Key Output |
|-------------------------------------------|--------------|-----------------------------|-------------|--------------------------------|
| [BRD Builder](brd-prd-builders) | Requirements | 3-phase Q&A | JSON state | Business requirements document |
| [PRD Builder](brd-prd-builders) | Requirements | 7-phase Q&A | JSON state | Product requirements document |
| [ADR Creator](adr-creation) | Architecture | 3-phase Frame/Decide/Govern | JSON state | Architecture decision record |
| [Security Planner](../security/README.md) | Security | 6-phase STRIDE | JSON state | Security model and backlog |

## Requirements

Expand Down Expand Up @@ -57,7 +57,7 @@ The Security Planner applies STRIDE-based security model analysis across seven o
> [!IMPORTANT]
> Run security planning after architecture decisions stabilize. Changes to infrastructure or service boundaries may invalidate earlier security models.

See the [Security Planning](../security/README) guide for the workflow, operational buckets, and invocation details.
See the [Security Planning](../security/README.md) guide for the workflow, operational buckets, and invocation details.

## Prerequisites

Expand Down Expand Up @@ -88,9 +88,9 @@ For greenfield projects, follow this order to build artifacts that feed into eac

## Related Documentation

* [RPI Documentation](../../rpi/README): Task research, planning, and implementation workflows
* [GitHub Backlog Manager](../github-backlog/README): Issue lifecycle management for GitHub repositories
* [ADO Backlog Manager](../ado-backlog/README): Work item management for Azure DevOps projects
* [RPI Documentation](../../rpi/README.md): Task research, planning, and implementation workflows
* [GitHub Backlog Manager](../github-backlog/README.md): Issue lifecycle management for GitHub repositories
* [ADO Backlog Manager](../ado-backlog/README.md): Work item management for Azure DevOps projects

---

Expand Down
2 changes: 1 addition & 1 deletion docs/agents/project-planning/arch-diagram-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Analyze the Terraform and Bicep files in this repository and create an ASCII arc

## Related Documentation

* [Project Planning Agents](README)
* [Project Planning Agents](README.md)
* [ADR Creator](adr-creation)

---
Expand Down
2 changes: 1 addition & 1 deletion docs/agents/project-planning/brd-prd-builders.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Output the PRD with measurable requirements in every section.
## Next Steps

1. Feed your completed BRD or PRD into the [ADR Creator](adr-creation) for architectural decisions
2. See [Project Planning Agents](README) for the full agent catalog
2. See [Project Planning Agents](README.md) for the full agent catalog

> [!TIP]
> Both agents work best when you provide a clear project name at invocation. The agents can derive a working title from context, but explicit scope accelerates the Assess phase.
Expand Down
4 changes: 2 additions & 2 deletions docs/agents/project-planning/security-plan-creator.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ This page has moved. The former Security Plan Creator agent is now the **Securit

## Where to Go

* [Security Planning](../security/README): Overview, six-phase workflow, operational buckets, and invocation details.
* [Security Planning](../security/README.md): Overview, six-phase workflow, operational buckets, and invocation details.
* [Entry Modes](../security/entry-modes): From-PRD and capture entry modes.
* [Phase Reference](../security/phase-reference): Phase-by-phase inputs, outputs, and state transitions.
* [Handoff Pipeline](../security/handoff-pipeline): Backlog generation and RAI Planner recommendation.

## Next Steps

1. Feed security findings into an [ADR](adr-creation) to document security architecture decisions
2. See [Project Planning Agents](README) for the full agent catalog
2. See [Project Planning Agents](README.md) for the full agent catalog

> [!TIP]
> Run the Security Planner after completing your [BRD or PRD](brd-prd-builders) to align threat analysis with documented requirements and system boundaries.
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"lint:version-consistency": "pwsh -NoProfile -Command \"./scripts/security/Test-ActionVersionConsistency.ps1 -FailOnMismatch -Format Json -OutputPath logs/action-version-consistency-results.json\"",
"lint:permissions": "pwsh -NoProfile -Command \"& './scripts/security/Test-WorkflowPermissions.ps1' -FailOnViolation\"",
"lint:dependency-pinning": "pwsh -NoProfile -Command \"& './scripts/security/Test-DependencyPinning.ps1' -FailOnUnpinned\"",
"lint:pr-gate": "pwsh -NoProfile -Command \"& './scripts/security/Test-PrValidationGate.ps1' -FailOnViolation\"",
"lint:ps-module-pins": "pwsh -NoProfile -File scripts/security/Test-PSModulePins.ps1",
"audit:pip": "pwsh -NoProfile -File scripts/security/Invoke-PipAudit.ps1",
"audit:npm": "audit-ci --config audit-ci.json",
Expand All @@ -34,7 +35,7 @@
"lint:ai-artifacts": "pwsh -NoProfile -Command \"& './scripts/linting/Validate-PlannerArtifacts.ps1' -FailOnMissing\"",
"lint:models": "pwsh -NoProfile -File scripts/linting/Test-ModelReferences.ps1 -OutputPath logs/model-validation-results.json",
"lint:models:refresh": "pwsh -NoProfile -File scripts/linting/Update-ModelCatalog.ps1",
"lint:all": "npm run format:tables && npm run lint:md && npm run lint:ps && npm run lint:yaml && npm run lint:json && npm run lint:links && npm run lint:frontmatter && npm run lint:adr-consistency && npm run lint:collections-metadata && npm run lint:marketplace && npm run lint:hooks && npm run lint:version-consistency && npm run lint:permissions && npm run lint:dependency-pinning && npm run lint:ps-module-pins && npm run lint:py && npm run validate:skills && npm run lint:ai-artifacts && npm run lint:models && npm run validate:devcontainer-lockfile && npm run eval:lint:vally && npm run eval:lint:schema && npm run eval:lint:text && npm run eval:lint:safety",
"lint:all": "npm run format:tables && npm run lint:md && npm run lint:ps && npm run lint:yaml && npm run lint:json && npm run lint:links && npm run lint:frontmatter && npm run lint:adr-consistency && npm run lint:collections-metadata && npm run lint:marketplace && npm run lint:hooks && npm run lint:version-consistency && npm run lint:permissions && npm run lint:dependency-pinning && npm run lint:pr-gate && npm run lint:ps-module-pins && npm run lint:py && npm run validate:skills && npm run lint:ai-artifacts && npm run lint:models && npm run validate:devcontainer-lockfile && npm run eval:lint:vally && npm run eval:lint:schema && npm run eval:lint:text && npm run eval:lint:safety",
"format:tables": "pwsh -NoProfile -File scripts/linting/Format-MarkdownTables.ps1",
"extension:prepare": "pwsh ./scripts/extension/Prepare-Extension.ps1 && npm run extension:postprocess",
"extension:prepare:prerelease": "pwsh ./scripts/extension/Prepare-Extension.ps1 -Channel PreRelease && npm run extension:postprocess",
Expand Down
10 changes: 10 additions & 0 deletions scripts/evals/Invoke-VallyEvals.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ $ErrorActionPreference = 'Stop'

Import-Module (Join-Path $PSScriptRoot 'Modules/StimulusIndex.psm1') -Force
Import-Module (Join-Path $PSScriptRoot 'Modules/VallyRunner.psm1') -Force
Import-Module (Join-Path $PSScriptRoot 'Modules/ArtifactDetection.psm1') -Force

if (-not (Get-Module -Name powershell-yaml)) {
Import-Module powershell-yaml -ErrorAction Stop
Expand Down Expand Up @@ -369,6 +370,15 @@ if ($null -ne $manifest -and $null -ne $manifest.artifacts) {
$artifacts = @($manifest.artifacts | Where-Object { [string]$_.status -ne 'D' })
}

# Repo-root (repo-specific) artifacts live directly under `.github/<kind>/`
# without a collection subdirectory. Per `.github/copilot-instructions.md` they
# are excluded from collection manifests, packaging, and eval coverage, so they
# carry no eval spec. Drop them here so they do not surface as missing-coverage
# failures, mirroring the skip in `Test-StimulusPresence.ps1`.
$artifacts = @($artifacts | Where-Object {
-not (Test-RepoRootArtifact -Kind ([string]$_.kind) -Path ([string]$_.path))
})

# Per-kind shard filter. When -Kind is supplied, the stimulus artifacts[] loop
# is narrowed to the matching kind(s) only. Baseline equivalence is cross-kind
# (an instruction/skill change can promote a parent agent), so it stays owned by
Expand Down
Loading
Loading