Skip to content

Worker protected-files: request_review is incompatible with signed commits (finding F) #1746

Closed

Description

@bradygaster

Summary

workflows/squad-implement-worker.md:170 sets protected-files: request_review. That value is incompatible with signed create-pull-request writes: the run logs that it is handling the protected-path write softly, then hard-refuses the signed push with Signed-commit payload violates file-protection policy.

This blocked the live end-to-end continuation test in bradygaster/aspiregregator-squad-test (finding F from the e2e run).

Mechanism

Verified against gh-aw v0.86.2 source:

  1. create_pull_request.cjs calls checkFileProtection(...), classifies request_review as a soft action, and logs that it will open the PR with a caution and a request-changes review.
  2. The same handler then calls pushSignedCommits(...).
  3. push_signed_commits.cjs synthesizes the GraphQL createCommitOnBranch payload and calls checkFileProtectionPostApply(...).
  4. Anything other than allow throws Signed-commit payload violates file-protection policy (...).

So the soft log and the hard refusal happen at different layers. request_review is effectively unusable for signed PR writes touching protected files.

fallback-to-issue takes a different route: the signed push still rejects the payload, but the PR handler has manifestProtectionFallback set, catches the failure, and opens a protected-file review issue instead.

Relevant gh-aw behavior

  • Default protected list: pkg/workflow/runtime_definitions.go:47-239 — every ecosystem manifest and lockfile, plus CODEOWNERS, DESIGN.md, README.md, CONTRIBUTING.md, CHANGELOG.md, SECURITY.md, CODE_OF_CONDUCT.md at :206-214. The Copilot engine adds AGENTS.md (copilot_engine.go:147-151).
  • Matching is basename-anywhere, not glob: manifest_file_helpers.cjs:301-305 does file.split("/").pop(). This is a different matcher from allowed-files globs, where * does not cross /.
  • The list is not replaceable, only narrowable. protected-files parses as a policy (create_pull_request.go:124,163-169); defaults are injected unconditionally (safe_outputs_handler_registry.go:568-572). The object form's exclude filters defaults at compile time (config_preprocessing.go:124-162, safe_outputs_config_generation.go:47-55).

Fix

protected-files:
  policy: fallback-to-issue
  exclude:
    - README.md

README.md is excluded because it is high-frequency, low-control-plane work that ordinary PR review already covers — protecting it at every depth is inherited from gh-aw's generic manifest-safety model rather than Squad's product model. Under plain fallback-to-issue, every README task would produce a review issue instead of a PR, which is the wrong default for a core Squad use case.

Everything genuinely load-bearing stays protected: dependency manifests and lockfiles, CODEOWNERS, SECURITY.md, CONTRIBUTING.md, CHANGELOG.md, and top-level dot folders. CHANGELOG.md specifically stays protected because in adopting repos it is often generated, is release provenance, and may satisfy a release gate.

Existing excluded-files rules are unchanged — they solve a different problem (stripping paths from the patch before protected-file evaluation) and remain independent.

Notes

  • Not protected-files: allowed. That would let the worker rewrite protected manifests and security docs.
  • Workflow source changes must be recompiled into the installed .lock.yml in any consuming/test repo; editing the Markdown source alone does not affect an already-compiled workflow.
  • Follow-up (not this issue): document fallback-to-issue as a deliberate safety handoff rather than a failed worker, and surface protected-file policy as an adoption-time repo configuration choice alongside the finding E Actions-permission preflight.

Validation

  • node scripts/check-workflow-input-interpolation.mjs
  • npx vitest run test/gh-aw-quality.test.ts (expect 81 passed / 13 skipped)

Activity

  1. added a commit that references this issue on Aug 20, 2026
    9ad363d
  2. added a commit that references this issue on Aug 20, 2026
    07985fe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions