Add hosted-agent PR policy checks - #983
Antriksh Jain (antriksh30) wants to merge 1 commit into
Conversation
Port credential-free hosted-agent contract and Python dependency policies to public pull requests. Keep shared test contracts and guidance under .azure-pipelines/hosted-agent-tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Validation gaps permit assertion-free contracts, malformed approval evidence, and inadequately specified dependency exceptions.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds credential-free hosted-agent policy enforcement for pull requests.
Changes:
- Adds contract and Python dependency policy workflows/checkers.
- Adds schema, fixture-path, exception, and regression-test support.
- Updates contributor documentation and ownership routing.
File summaries
| File | Description |
|---|---|
samples/python/hosted-agents/DEPENDENCY_POLICY.md |
Documents public dependency validation. |
samples/python/hosted-agents/AGENTS.md |
Updates Python contract guidance. |
samples/csharp/hosted-agents/AGENTS.md |
Updates C# contract guidance. |
CONTRIBUTING.md |
Describes new PR checks. |
.github/workflows/hosted-agent-policies.yml |
Defines policy jobs. |
.github/scripts/test/test_hosted_agent_policies_workflow.py |
Tests workflow security properties. |
.github/scripts/test/test_hosted_agent_fixture.py |
Tests fixture path mapping. |
.github/scripts/test/test_check_hosted_agent_python_requirements.py |
Tests dependency policy. |
.github/scripts/test/test_check_hosted_agent_contracts.py |
Tests contract coverage. |
.github/scripts/requirements.txt |
Adds packaging dependency. |
.github/scripts/hosted_agent_test_spec.py |
Implements contract validation and evaluation. |
.github/scripts/hosted_agent_fixture.py |
Maps samples to fixtures. |
.github/scripts/check-hosted-agent-python-requirements.py |
Enforces dependency reproducibility. |
.github/scripts/check_hosted_agent_contracts.py |
Enforces new-sample contracts. |
.github/CODEOWNERS |
Routes fixture ownership. |
.azure-pipelines/hosted-agent-tests/README.md |
Documents contract schema and workflow. |
.azure-pipelines/hosted-agent-tests/python-requirements-exceptions.toml |
Defines dependency exceptions. |
Review details
Suppressed comments (2)
.github/scripts/hosted_agent_test_spec.py:492
- Falsey non-array values such as
{},"", or0are coerced to an empty list here, so malformed Responses evidence can be reported as having no approval requests (and even as sequence-complete) instead of failing closed. Default only a missing key, then let the existing type check reject every non-list value.
output = response.get("output") or []
.github/scripts/hosted_agent_test_spec.py:368
- The validator permits a contract with no turn- or test-level assertions because both assertion collections default to empty. Such a contract passes the new PR policy but only checks execution success, contrary to the required “assertions for its defining behavior” in
samples/python/hosted-agents/AGENTS.md:52-55; require at least one assertion somewhere in the document.
return document
- Files reviewed: 17/17 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| missing = {"path", "code", "reason", "owner", "issue", "expires"} - raw.keys() | ||
| if missing: | ||
| raise CheckError(f"{path}: exception {index} is missing {sorted(missing)}") |
| if "exists" in predicate and not isinstance(predicate["exists"], bool): | ||
| raise SpecError(f"{context}.exists must be a boolean") | ||
| if "regex" in predicate: | ||
| _compile_regex(predicate["regex"], f"{context}.regex") |
| CI rejects any fixture whose full path does not map back to a sample containing | ||
| `azure.yaml`. |
|
|
||
| findings: list[Finding] = [] | ||
| for root, root_triggers in sorted(triggers.items(), key=lambda item: str(item[0])): | ||
| source = root / "requirements.txt" |
There was a problem hiding this comment.
The required policy currently unconditionally selects requirements.txt. A new or dependency-updated uv-native runtime with pyproject.toml + uv.lock therefore fails PYREQ001/PYREQ006, even though that is the intended future format. Because this check will block merges, it should accept either a fully resolved requirements.txt or a valid pyproject.toml + uv.lock.
| _validate_assertion( | ||
| assertion, "test", f"{context}.assertions[{assertion_index}]" | ||
| ) | ||
| return document |
There was a problem hiding this comment.
Assertion collections currently default to empty, so an assertion-free contract passes. This does not need to block this PR, but it is worth tracking a follow-up to require at least one defining-behavior assertion.
| group: hosted-agent-policies-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: |
There was a problem hiding this comment.
These checks are currently advisory: the public main ruleset still requires only trusted. Please track adding both new job contexts as required checks after the workflow merges and passes a proof PR.
Summary
.azure-pipelines/hosted-agent-tests/, preserving the full language/framework/sample path.Execution boundary
Both jobs use
pull_request, a read-only token, and checkout without persisted credentials. They can run on fork PRs subject to GitHub approval and require no Azure secrets or OIDC access. This change does not enable cloud deployment, modify the existingtrustedgate or merge rules, or re-enable disabled workflows.Historical cloud fixtures and ADO pipeline wiring are separate follow-up work.