Agent PR Submission Pipeline
에이전트 PR 제출 파이프라인
Section titled “에이전트 PR 제출 파이프라인”FractalOps는 PR 제출을 템플릿 범위의 권능(capability) 으로 다루지 — 일반 에이전트
특권으로 다루지 않습니다. 정책은 access/application/studio/pr_submission_policy.py에
코드로 고정되어 있고, 전송(transport)은 CodexGate GitHub App을 통해 봇으로 발행합니다.
계약(Contract)
Section titled “계약(Contract)”상수는 pr_submission_policy.py에 그대로 있습니다:
allowed_write_policy: report-only(REPORT_ONLY_WRITE_POLICY) — 에이전트는 issue와 증거를 보고할 수 있지만 branch나 PR을 claim할 수 없습니다.normalize_write_policy는 빈 값,read-only,report-only를 모두 여기로 모읍니다.allowed_write_policy: agent-branch-pr-only(AGENT_BRANCH_PR_ONLY_POLICY) — 에이전트는 배정된 branch prefix와 PR 파이프라인을 통해서만 제출할 수 있습니다.github-pr-only/pr-only도 여기로 정규화됩니다.pr_submission_policy: selective-agent-pr(PR_SUBMISSION_POLICY_SELECTIVE) — 에이전트 id가pr_submitter_agent_ids에 들어 있지 않으면 파이프라인을 fail-closed로 둡니다.pr_submission_pipeline은 durable transport의 이름입니다. Studio는codexgate-github-app-pr(PR_SUBMISSION_PIPELINE상수)을 씁니다. CodexGate 리포지토리 정책은github-app-draft-pr을 씁니다.
판정 함수는 pr_submission_allowed(...)입니다:
def pr_submission_allowed( *, agent_id: object, allowed_write_policy: object, pr_submitter_agent_ids: object, explicit_allowed: object = None,) -> bool: if explicit_allowed is not None: return bool(explicit_allowed) normalized_agent = text(agent_id).strip() return ( normalize_write_policy(allowed_write_policy) == AGENT_BRANCH_PR_ONLY_POLICY and normalized_agent in set(normalized_agent_ids(pr_submitter_agent_ids)) )즉 PR 제출이 허용되려면 (1) write policy가 agent-branch-pr-only이고 (2) 에이전트 id가
submitter 목록에 있어야 합니다(또는 세션 메타데이터의 pr_submission_allowed로 명시
허용). 이 게이트는 assert_report_pr_submission_allowed에서 강제됩니다 — 보고된 attributes에
branch_name 또는 pr_url(즉 PR delivery claim)이 있는데 허용되지 않으면
agent_pr_submission_not_allowed를 raise합니다.
게이트(Gates)
Section titled “게이트(Gates)”flowchart TD
report["에이전트 report\n(branch_name? / pr_url?)"]
claim{"has_pr_delivery_claim?\n(branch_name 또는 pr_url)"}
allow{"pr_submission_allowed?\n(agent-branch-pr-only\n+ submitter 목록)"}
prefix{"branch가 허용 prefix\n또는 agent/<lane>/ 와 일치?"}
ok["report 수락\n-> codexgate-github-app-pr 전송"]
rejclaim["claim 없음:\n그냥 보고로 수락"]
rejallow["reject:\nagent_pr_submission_not_allowed"]
rejprefix["reject:\nagent_pr_branch_prefix_violation"]
report --> claim
claim -->|no| rejclaim
claim -->|yes| allow
allow -->|no| rejallow
allow -->|yes| prefix
prefix -->|no| rejprefix
prefix -->|yes| ok
- Studio 템플릿은 submitter 목록과 에이전트별
pr_submission_allowed플래그를 발행합니다. - Studio 세션 메타데이터는 활성 에이전트에 대해 그 정책을 미러링합니다.
- HUD report 인제스션은 세션이 PR 제출을 부여하지 않으면
branch_name또는pr_url을 거부합니다. - CodexGate 발행은 선택된 에이전트가 리포지토리 정책에 의해 허용되지 않으면
publish=True를 거부합니다. - branch prefix 검사(
_branch_matches_allowed_submission_target)는 branch가allowed_write_prefix로 시작하거나, 세션의 정식 branch 이름과 같거나,agent/<lane>/...(lane = agent_id 또는 role_key) 형태일 때만 통과시킵니다. 어긋나면agent_pr_branch_prefix_violation.
기본값(Default)
Section titled “기본값(Default)”AgentSquad는 기본적으로 report-only입니다. forge가 유일한 기본 Studio PR submitter입니다.
CodexGate는 crux-portal과 sable-runtime을 허용하고, mira-evidence는 report-only로
남습니다.
쓰기 행위자(Write Actor)
Section titled “쓰기 행위자(Write Actor)”전송은 raw org PAT가 아니라 CodexGate GitHub App(fractalops-codexgate[bot])으로
발행합니다. AgentSquad의 PR과 issue는 App 설치(installation)가 작성합니다:
- App id
3249317, installation120794317,yamoncoorg(all-repo). CodexGateGitHubAppService._installation_token이 git 인증과 GitHub REST/GraphQL 호출용으로 실제ghs_…installation 토큰을 mint합니다.repository_materialization이 이미 git 인증을 이 경로로 라우팅하고 있어서, App이 온라인이 됐을 때 app 코드는 바뀌지 않았습니다.codexgate_github_bot_actor는 실제 App slug와 맞추기 위해fractalops-codexgate[bot]입니다.
App은 이전에 두 가지 이유로 무력(inert)했고, 지금은 둘 다 고쳐졌습니다: 크리덴셜
(app_id / installation_id / private_key)이 프로비저닝된 적이 없었고, 남아 있던
FRACTALOPS_GITHUB_APP_TOKEN override env(org PAT)가 _installation_token 안에서 App 크리덴셜을
이겼습니다(메서드가 override를 먼저 반환). override env는 모든 곳에서 제거됐고, App 크리덴셜은
k8s secret fractalops-codexgate-github-app에서 공급됩니다. API, worker, Studio worker가
envFrom으로 소비하며 provider workspace에는 private key를 전달하지 않습니다.
이 secret은 오늘날 수동으로 프로비저닝됩니다 — org-PAT fractalops-github-runtime secret과
같은 패턴입니다. 이를 OpenBao + ExternalSecret으로 옮기는 것은 pending follow-up입니다.
Merge lifecycle decision
Section titled “Merge lifecycle decision”delivery reference(PR/issue)가 있다고 lane이 닫히는 것은 아닙니다. committer는 연결된 PR과
tester 증명을 검토한 뒤 merge lifecycle decision을 닫아야 합니다. 정식 런타임 blocker는
merge_lifecycle_decision_required이고, 닫는 방법은 둘 중 하나입니다:
handoff_state=merge_requested + merge_gate_status=qa_passed, 또는 handoff_state=merged.
committer_merge_state_required는 retired wire field일 뿐입니다.
(AgentSquad Delivery Language 참고.)