Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/agent-law-provisioner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Agent Law Provisioner

on:
schedule:
- cron: "17 9 * * *"
workflow_dispatch:
inputs:
owner:
description: "Owner/org to provision. Defaults to this repository owner."
required: false
default: ""
apply:
description: "Actually create rulesets and repair PRs. Requires AGENT_LAW_ADMIN_TOKEN for cross-repo writes."
required: false
default: "true"
type: choice
options: ["true", "false"]
ensure_org_ruleset:
description: "Attempt owner-level organization ruleset creation when owner is an org."
required: false
default: "true"
type: choice
options: ["true", "false"]

permissions:
contents: read

jobs:
provision-agent-law:
name: provision-agent-law
runs-on: ubuntu-latest
steps:
- name: Checkout hub
uses: actions/checkout@v4

- name: Provision Agent Law
env:
AGENT_LAW_ADMIN_TOKEN: ${{ secrets.AGENT_LAW_ADMIN_TOKEN }}
WORKFLOW_OWNER: ${{ github.repository_owner }}
INPUT_OWNER: ${{ inputs.owner }}
INPUT_APPLY: ${{ inputs.apply }}
INPUT_ENSURE_ORG_RULESET: ${{ inputs.ensure_org_ruleset }}
GITHUB_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

OWNER="${INPUT_OWNER:-}"
if [[ -z "$OWNER" ]]; then
OWNER="$WORKFLOW_OWNER"
fi

APPLY="${INPUT_APPLY:-true}"
ENSURE_ORG_RULESET="${INPUT_ENSURE_ORG_RULESET:-true}"

if [[ -n "${AGENT_LAW_ADMIN_TOKEN:-}" ]]; then
export GH_TOKEN="$AGENT_LAW_ADMIN_TOKEN"
else
export GH_TOKEN="$GITHUB_TOKEN"
echo "::warning::AGENT_LAW_ADMIN_TOKEN is not configured. Running audit-only because the default GITHUB_TOKEN is repo-scoped and cannot provision other repositories."
APPLY="false"
fi

args=(--owner "$OWNER" --ensure-repo-rulesets --repair-files)
if [[ "$APPLY" == "true" ]]; then
args+=(--apply)
fi
if [[ "$ENSURE_ORG_RULESET" == "true" ]]; then
args+=(--ensure-org-ruleset)
fi

python3 scripts/provision-agent-law.py "${args[@]}"

- name: Upload provisioner report
if: always()
uses: actions/upload-artifact@v4
with:
name: agent-law-provisioner-results
path: agent-law-provisioner-results.json
if-no-files-found: ignore
44 changes: 44 additions & 0 deletions docs/agent-law/provisioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Agent Law Provisioner

The Agent Law provisioner is the durable repair loop for the Empower Orchestrator law.

It exists because default community files and local dotfiles are not enough: each repository needs repo-local doctrine, a PR checklist, an `agent-law` workflow, and branch rules requiring that workflow.

## What it provisions

For every active, non-archived, non-fork repo under the selected owner it can:

1. Ensure an `Agent Law` repository ruleset exists.
2. Attempt an owner-level organization ruleset when the owner is an organization and the token has `admin:org`.
3. Open a repair PR if repo-local Agent Law files are missing or drifted.

## Required secret

Configure `AGENT_LAW_ADMIN_TOKEN` in this hub repository.

For `KyaniteLabs/.github`, use a token or GitHub App installation that can:

- list all org repositories, including private repos
- administer repository rulesets
- create branches and PRs
- write workflow files
- create organization rulesets if you want the single org-level ruleset

A classic PAT needs at least `repo`, `workflow`, and `admin:org` for the KyaniteLabs org-level ruleset path. Fine-grained tokens/apps are better if scoped to the org with repository administration and contents/pull-request/workflow write permissions.

For `simongonzalezdc/.github`, personal repositories do not have an organization-level ruleset surface; the provisioner uses per-repo rulesets plus repair PRs.

## Operating modes

- Scheduled runs automatically apply only when `AGENT_LAW_ADMIN_TOKEN` exists.
- Without that secret, the workflow falls back to audit-only and emits a warning.
- Manual dispatch can set `apply=false` for dry runs.

## Local smoke

```bash
python3 -m py_compile scripts/provision-agent-law.py
python3 scripts/provision-agent-law.py --owner KyaniteLabs --ensure-org-ruleset --ensure-repo-rulesets --repair-files
```

Omit `--apply` for audit-only. Add `--apply` only when the token has the necessary write/admin permissions.
Loading
Loading