# aahp-govern.yml - Portable AAHP governance gate for consumer repositories.
#
# Drop this into .github/workflows/ (or let `aahp init --gates` scaffold it) to
# run the AAHP governance gates on every push and pull request. It invokes the
# pinned @elvatis_com/aahp devDependency by PATH, inside node_modules, so the
# only thing it can execute is the package `npm ci` placed from the committed
# lockfile. Verify-only: it never mutates the repository, and it honors no skip
# or bypass environment variable.
#
# Why a path and not `npx`. Earlier versions of this file had both steps read
# `npx --no-install aahp ...`. Whenever the local resolution missed - lockfile
# drift, a workspace layout, an edited or reordered install step, a cache
# failure - that line asked registry.npmjs.org about the UNSCOPED public name
# `aahp`, and whether it then refused depended on npm's flag handling: the `npx`
# binary stops (measured on npm 10 to 12, AAHP docs/adr/ADR-013.md), while
# `npm exec --no-install` on npm 10 and 11 downloads and runs whatever comes
# back, which would have run as this repository's governance gate. The published package
# is `@elvatis_com/aahp`; the unscoped name belongs to nobody, so the fallback did
# not even resolve to a stale version of this project. The line below cannot
# reach the registry and cannot resolve to any name but the pinned one: if
# `npm ci` did not place it, `node` exits non-zero and the job fails closed.
#
# If you copied an earlier version of this file into your repository, re-scaffold
# it with `aahp init --gates --workflows`, which rewrites only the workflow files
# (`aahp doctor` reports a stale copy in its cli-source gate); fixing it here
# does not fix your copy.
#
# This workflow runs NO handoff-integrity gate, and neither of its two steps
# stands in for one. `aahp check` runs the config-driven governance gates only:
# it has no file-set gate and no index gate. `aahp doctor --governance`, the
# step below, marks handoff-set, manifest-schema and grounding as `skip`
# WITHOUT evaluating them. Comparing a recorded checksum against the bytes on
# disk is `aahp verify` Layer 1's job; ADR-011 assigns handoff drift to
# `aahp verify`. If this repository also keeps `.ai/handoff/`, copy
# node_modules/@elvatis_com/aahp/assets/governance/aahp-verify.yml beside this
# file as .github/workflows/aahp-verify.yml and make it a required status check
# (`aahp init --gates` writes that copy itself when .ai/handoff/ exists).
# (Not the aahp-verify.yml in the AAHP repository's own .github/workflows/: that
# one runs the gate from an AAHP checkout and fails anywhere else.) Without it
# no gate here compares a handoff checksum, and a green conformance record is a
# statement about conformance, not integrity.
#
# `aahp lint` is not a substitute either, least of all here: its checksum
# comparison runs only under a Python interpreter, and this workflow sets up
# Node and not Python. With no interpreter present lint reports that MANIFEST
# integrity was NOT verified and still exits 0, so it would turn a drifted tree
# green. `aahp verify` Layer 1 fails outright when it has no interpreter.
#
# Prerequisites in the consumer repo:
#   - @elvatis_com/aahp pinned as an exact devDependency (npm i -D -E @elvatis_com/aahp)
#   - a committed package-lock.json (npm ci needs it)
#   - an aahp.config.json (see `aahp init --gates`)
#
# Hardening, and why it is stated here rather than left to the adopting repo:
# AAHP cannot know an adopter's repository visibility, their
# `default_workflow_permissions` setting, or whether an organization default
# grants `write`. So this file declares what it needs instead of inheriting it.
#   - `permissions: contents: read` is the whole grant. This workflow only reads
#     the checkout and runs `aahp` locally; it opens no issue, posts no comment
#     and pushes nothing. Without this block the job inherits the repository
#     default, and in a repository whose default is `write` that hands a
#     write-capable GITHUB_TOKEN to `npm ci` and to everything `aahp` executes.
#   - `persist-credentials: false` keeps that token out of `.git/config`.
#     actions/checkout defaults it to true, which writes the token into the
#     workspace where every later step in the job can read it. Nothing here
#     needs it: the checkout is the only network git operation in the job.
# If you add a step that pushes, revisit both lines deliberately rather than
# deleting them.
name: AAHP Govern

permissions:
  contents: read

on:
  push:
    branches: [main]
  pull_request:
jobs:
  govern:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
        with:
          # Node 22 is the floor engines.node publishes for @elvatis_com/aahp.
          # `aahp init --gates` copies this file into a consumer repository
          # byte-identical, so this pin is the runtime every adopting repo runs
          # the gates on. A lower pin does not fail loudly: `npm ci` emits
          # EBADENGINE and carries on, so the CLI then runs on a runtime the
          # package does not claim to support. scripts/check-runtime-support.mjs
          # scans this directory for exactly that reason - see its SCAN_ROOTS.
          node-version: '22'
      - name: Install pinned aahp devDependency
        run: npm ci --ignore-scripts
      - name: Run governance gates
        run: node ./node_modules/@elvatis_com/aahp/bin/aahp.js check .
      - name: Governance conformance record
        run: node ./node_modules/@elvatis_com/aahp/bin/aahp.js doctor --governance --json .
