feat(agent-docs-audit): policy, deterministic scanner, and weekly semantic audit workflow #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Agent docs audit | |
| # Audit agent-context docs (CLAUDE.md, AGENTS.md, .claude/rules/) against | |
| # agent-docs-policy.md. | |
| # | |
| # Two layers: | |
| # L1 (deterministic): line budgets, symlink/pair integrity, broken @imports, | |
| # broken path refs, unresolved commands. No API calls. | |
| # L2 + L3 (semantic): Haiku triage filters L1's flagged set; Sonnet verifies | |
| # concrete claims via Read/Glob/Grep and produces | |
| # KEEP/TRIM/MOVE/UPDATE/INVESTIGATE findings. | |
| # | |
| # Warning-only for now. Uploads artifacts and writes a Step Summary; does not | |
| # post PR comments, does not fail the workflow on findings. | |
| # | |
| # AI layers are skipped automatically if ANTHROPIC_API_KEY is unavailable | |
| # (fork PRs, secret not set). In that case the L1 report still uploads. | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| # Weekly on Monday 14:00 UTC | |
| - cron: '0 14 * * 1' | |
| pull_request: | |
| paths: | |
| - '**/AGENTS.md' | |
| - '**/CLAUDE.md' | |
| - '**/CLAUDE.local.md' | |
| - '.claude/rules/**' | |
| - 'agent-docs-policy.md' | |
| - '.github/scripts/agent-docs-audit*' | |
| - '.github/scripts/agent-docs-l1*' | |
| - '.github/workflows/agent-docs-audit.yml' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: agent-docs-audit-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| audit: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| # Detect whether AI layers can run. | |
| # | |
| # SECURITY: PR-triggered runs always fall back to L1-only. | |
| # The audited input is markdown (CLAUDE.md, AGENTS.md) which is | |
| # itself prompt text and can be modified in the PR. Running a | |
| # tool-using model (Read/Glob/Grep/Bash) over PR-authored prompt | |
| # files while ANTHROPIC_API_KEY is in env would be a prompt- | |
| # injection pathway. risk-assess.yml is safer because its input | |
| # is a code diff and it only allows Read/Glob/Grep. Until our | |
| # threat model matches that, L2/L3 only run on scheduled and | |
| # workflow_dispatch events (input is main, trusted by review). | |
| - name: Detect AI eligibility | |
| id: ai | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping AI layers on pull_request - running L1 (deterministic drift) only" | |
| elif [ -z "${{ secrets.ANTHROPIC_API_KEY }}" ]; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping AI layers - no ANTHROPIC_API_KEY in repo secrets" | |
| else | |
| echo "skip=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Install script deps | |
| if: steps.ai.outputs.skip != 'true' | |
| run: npm install --prefix .github/scripts @anthropic-ai/claude-agent-sdk @anthropic-ai/sdk | |
| - name: Run audit (L1 + L2 + L3) | |
| if: steps.ai.outputs.skip != 'true' | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| REPO_ROOT: ${{ github.workspace }} | |
| run: | | |
| node .github/scripts/agent-docs-audit.mjs > /tmp/agent-docs-audit-summary.md | |
| cat /tmp/agent-docs-audit-summary.md | |
| - name: Run audit (L1 only) | |
| if: steps.ai.outputs.skip == 'true' | |
| env: | |
| REPO_ROOT: ${{ github.workspace }} | |
| run: | | |
| node .github/scripts/agent-docs-audit.mjs --skip-ai > /tmp/agent-docs-audit-summary.md | |
| cat /tmp/agent-docs-audit-summary.md | |
| - name: Write step summary | |
| if: always() | |
| run: | | |
| if [ -f /tmp/agent-docs-audit-summary.md ]; then | |
| cat /tmp/agent-docs-audit-summary.md >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Upload audit artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: agent-docs-audit | |
| path: | | |
| /tmp/agent-docs-audit-summary.md | |
| /tmp/agent-docs-audit.json | |
| /tmp/agent-docs-audit-l1.md | |
| if-no-files-found: warn | |
| retention-days: 30 |