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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"
- "ci"
commit-message:
prefix: "ci(deps)"
6 changes: 4 additions & 2 deletions .github/workflows/agent-law-provisioner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout hub
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Provision Agent Law
env:
Expand Down Expand Up @@ -73,7 +75,7 @@ jobs:

- name: Upload provisioner report
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: agent-law-provisioner-results
path: agent-law-provisioner-results.json
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/agent-law.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Verify Empower Orchestrator law
shell: bash
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/blacksmith-go-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ jobs:
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: true
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/blacksmith-probe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Runner identity
run: |
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI

on:
pull_request:
merge_group:
workflow_dispatch:

permissions:
contents: read

jobs:
python-tests:
name: Python tests
runs-on: ubuntu-latest
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the required Blacksmith runner for CI

This newly added CI job runs on ubuntu-latest, but the repository instructions in /workspace/.github/AGENTS.md require CI checks to run on blacksmith-2vcpu-ubuntu-2404. Because this workflow is intended to provide the repo's Python test coverage, it will either fail org policy expectations or leave the new required check running on the wrong runner class; please switch this job to the Blacksmith runner.

Useful? React with 👍 / 👎.

steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Run unit tests
run: python3 -m unittest discover -s tests
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
.env
.env.*
!.env.example
*.pem
*.key
.idea/
.vscode/
*.swp
Expand All @@ -18,6 +20,8 @@
.omc/

# Generated logs and archives
__pycache__/
*.py[cod]
*.log
npm-debug.log*
pnpm-debug.log*
Expand Down
7 changes: 5 additions & 2 deletions scripts/provision-agent-law.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ def workflow_text() -> str:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false

- name: Verify Empower Orchestrator law
shell: bash
Expand Down Expand Up @@ -337,7 +339,8 @@ def upsert_marker_file(path: Path, block: str, header: str) -> None:

def choose_recipe_path(repo_dir: Path) -> Path:
# Respect repos that already use a capitalized Docs tree on case-insensitive machines.
if (repo_dir / "Docs").exists() and not (repo_dir / "docs").exists():
names = {child.name for child in repo_dir.iterdir()} if repo_dir.exists() else set()
if "Docs" in names and "docs" not in names:
return repo_dir / "Docs" / "agent-law" / "empower-orchestrator.md"
return repo_dir / "docs" / "agent-law" / "empower-orchestrator.md"

Expand Down
91 changes: 91 additions & 0 deletions tests/test_agent_defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from __future__ import annotations

import importlib.util
import sys
import tempfile
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]


def load_script(name: str, path: Path):
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
assert spec.loader is not None
sys.modules[name] = module
spec.loader.exec_module(module)
return module


parity = load_script("check_agent_parity", ROOT / "scripts" / "check-agent-parity.py")
provisioner = load_script("provision_agent_law", ROOT / "scripts" / "provision-agent-law.py")


class AgentParityTests(unittest.TestCase):
def test_strip_agent_specific_removes_markers_and_normalizes(self) -> None:
content = """---
title: hidden
---
# Rules
<!-- private -->
<agent>ignore</agent>


Keep this.
"""

self.assertEqual(parity.strip_agent_specific(content), "# Rules\n\nignore\n\nKeep this.")

def test_extract_sections_keeps_nested_section_names(self) -> None:
sections = parity.extract_sections("# One\nAlpha\n\n## Two\nBeta")

self.assertEqual(sections["One"], "Alpha")
self.assertEqual(sections["Two"], "Beta")

def test_check_repo_fails_when_agents_file_is_missing(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp) / "example"
repo.mkdir()
(repo / "CLAUDE.md").write_text("# Organization Principles\n\nUseful over flashy.\n")

result = parity.check_repo(repo)

self.assertEqual(result.status, "fail")
self.assertIn("AGENTS.md file is missing", result.content_differences)


class ProvisionerTests(unittest.TestCase):
def test_upsert_marker_file_replaces_existing_block(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / "AGENTS.md"
path.write_text(f"# Rules\n\n{provisioner.START}\nold\n{provisioner.END}\n")

provisioner.upsert_marker_file(path, f"{provisioner.START}\nnew\n{provisioner.END}", "# Rules")

text = path.read_text()

self.assertIn("new", text)
self.assertNotIn("old", text)
self.assertEqual(text.count(provisioner.START), 1)

def test_choose_recipe_path_respects_capitalized_docs_tree(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp)
(repo / "Docs").mkdir()

path = provisioner.choose_recipe_path(repo)

self.assertEqual(path, Path(tmp) / "Docs" / "agent-law" / "empower-orchestrator.md")

def test_generated_workflow_uses_pinned_checkout_without_credentials(self) -> None:
text = provisioner.workflow_text()

self.assertIn("actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5", text)
self.assertIn("persist-credentials: false", text)
self.assertNotIn("actions/checkout@v4", text)


if __name__ == "__main__":
unittest.main()
Loading