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
49 changes: 49 additions & 0 deletions .fullsend/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# fullsend per-repo configuration
# https://github.com/fullsend-ai/fullsend
#
# This file configures fullsend for per-repo installation mode.
# See https://fullsend.sh/docs/guides/infrastructure/layered-config-reference
version: "1"
roles:
- fullsend
- triage
- coder
- fix
- review
- retro
- prioritize
agents:
- name: review
source: customized/harness/review.yaml
- name: retro
source: customized/harness/retro.yaml
allowed_remote_resources:
- https://raw.githubusercontent.com/fullsend-ai/fullsend/
- https://raw.githubusercontent.com/fullsend-ai/agents/
create_issues:
allow_targets:
repos:
- conforma/conforma.github.io
- fullsend-ai/fullsend
status_notifications:
comment:
completion: on_failure
reaction:
start: enabled
completion: disabled
21 changes: 21 additions & 0 deletions .fullsend/customized/harness/retro.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# Derived retro harness: retain upstream analysis and append the Conforma gate.
base: https://raw.githubusercontent.com/fullsend-ai/agents/69ade99f1b61bea99aee98e604384e26ff7b45e0/harness/retro.yaml#sha256=6d858c90cc6f1c7526d2b36b8cd47df079d1332ac7184bb70dfb1587e9cb04d8

skills:
- customized/skills/retro-filing-policy
27 changes: 27 additions & 0 deletions .fullsend/customized/harness/review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

base: https://raw.githubusercontent.com/fullsend-ai/agents/440d3e3c1a4a770309e37c2fd2826dfc88297d99/harness/review.yaml#sha256=c259d94e7c50e5e01cb0fa38df2b70765f8e35beb7ad8bf006c9193a05589917

# Fullsend's bool merge treats an omitted readonly_repo as false, so carry
# forward the upstream read-only guarantee explicitly.
readonly_repo: true

env:
runner:
REVIEW_FINDING_SEVERITY_THRESHOLD: "high"
sandbox:
REVIEW_FINDING_SEVERITY_THRESHOLD: "high"
66 changes: 66 additions & 0 deletions .fullsend/customized/skills/retro-filing-policy/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: retro-filing-policy
description: >-
Required on every Conforma retro run. Score every candidate from 0 to 5
and file only score-4 and score-5 findings after duplicate checks.
---

# Conforma retro filing policy

This skill is mandatory for every retro run. Invoke it before writing
`$FULLSEND_OUTPUT_DIR/agent-result.json`. It augments the upstream retro
analysis and does not replace its workflow reconstruction, duplicate checks,
recently-closed checks, evidence handling, or proposal limit.

## Required filing sequence

1. Build the complete candidate list from the upstream retro analysis.
2. Before deciding what belongs in `proposals[]`, assign every candidate an
integer judge score from 0 through 5 using the rubric below.
3. Apply the upstream checks for an existing open duplicate or a substantially
equivalent issue closed recently. A duplicate or recently closed equivalent
is summary-only even when its score is 4 or 5. Supporting evidence for an
existing issue is summary-only and must never become an "Evidence for ..."
proposal.
4. Put only eligible, non-duplicate candidates scored 4 or 5 in `proposals[]`.
Preserve the upstream maximum of three proposals, keeping the highest-value
candidates when there are more than three.
5. Keep every score-0-through-3 candidate out of `proposals[]`. Mention it in
the retro `summary` as summary-only, with a compact reason.
6. In the `summary`, include a compact **Judge scores** list covering every
candidate, filed and summary-only. Each entry must contain the score, a
short title, and the disposition (`filed` or `summary-only`).
7. For every filed proposal, begin the existing
`what_could_go_better` text field with:

`Judge score: N/5 — <one-line justification>`

Do not add new JSON fields or change the upstream result schema.

Do not create, edit, or post issues yourself. The upstream post-script handles
writes after output validation.

## Conforma scoring rubric

Score the impact of the candidate, not how interesting the observation is.
Use the lower range by default for isolated improvements:

- One-off pitfalls, cosmetic documentation edits, historical-document
cleanup, speculative prevention rules, and isolated preferences score 0–3
by default. They are not eligible for filing without evidence that a higher
threshold applies.
- An `AGENTS.md` proposal scores 0–3 by default. It can score 4 or 5 only
when there is evidence of a recurring contributor or agent failure, the rule
applies to human contributors as well as bots, and the instruction has a
credible preventive mechanism.

Use score 4 only when there is a likely recurring impact, such as repeated
human time loss, repeated bad bot output, pipeline or policy integrity risk,
or persistent operational cost.

Use score 5 only for a systemic or recurring correctness, security,
reliability, or policy failure.
Comment thread
st3penta marked this conversation as resolved.

A high score does not bypass the upstream duplicate, recently-closed, or
evidence-for checks. If those checks suppress a candidate, list it as
summary-only and explain the disposition in the summary.
122 changes: 91 additions & 31 deletions .github/workflows/fullsend.yaml
Original file line number Diff line number Diff line change
@@ -1,64 +1,94 @@
# lint-workflow-size: max-lines=280
# fullsend shim workflow (workflow_call mode)
# Routes events to agent workflows in .fullsend via workflow_call.
# No secrets are needed in the enrolled repo — agents fetch scoped tokens
# from the centralized token mint using GitHub OIDC.
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# This file is managed by fullsend. Do not edit it directly.
# Upstream: https://github.com/fullsend-ai/fullsend/blob/main/internal/scaffold/fullsend-repo/.github/workflows/fullsend.yaml
---
# fullsend shim workflow (per-repo installation mode)
# Routes events to agent workflows via reusable-dispatch.yml.
# All agent execution happens in this repo's context — no external
# config repo is needed.
#
# Security: pull_request_target runs the BASE branch version of this workflow,
# preventing PRs from modifying it to exfiltrate credentials.
# This shim never checks out PR code, so it is not vulnerable to "pwn request"
# attacks.
#
# conforma is replaced by reconcile-repos.sh at deploy time.
# Routing: this shim forwards the raw event context to reusable-dispatch.yml,
# which determines the stage and runs the agent inline (ADR 62).
# Adding a new stage requires only a job in reusable-dispatch.yml — zero changes to this repo.
#
# Routing: this shim forwards the raw event context to dispatch.yml, which
# determines the stage from event_type + event_action + payload fields.
# Adding a new stage requires only a case branch in dispatch.yml — zero
# changes to enrolled repos.
# Concurrency: per-role cancel-in-progress groups live in reusable-dispatch.yml
# stage jobs with -agent- suffix. Roles operate independently (#2452).
name: fullsend

permissions:
actions: write
id-token: write
contents: read
pull-requests: read

on:
issues:
types: [opened, edited, labeled]
issue_comment:
types: [created]
pull_request_target:
types: [opened, synchronize, ready_for_review, closed]
types: [opened, synchronize, ready_for_review, closed, labeled, unlabeled]
pull_request_review:
types: [submitted]

permissions: {}

jobs:
dispatch:
concurrency:
group: fullsend-dispatch-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
if: >-
github.event_name != 'issue_comment'
|| github.event.comment.user.type != 'Bot'
uses: conforma/.fullsend/.github/workflows/dispatch.yml@f44ff36aed88e798182d1a316bbfca943c23295a # main
(github.event_name != 'pull_request_target' && github.event_name != 'pull_request_review'
|| github.event.pull_request.head.ref != 'fullsend/scaffold-install')
&& (github.event_name != 'issue_comment'
|| (startsWith(github.event.comment.body, '/fs-')
&& github.event.comment.user.type != 'Bot'))
permissions:
actions: write
id-token: write
contents: write
issues: write
packages: read
pull-requests: write
uses: fullsend-ai/fullsend/.github/workflows/reusable-dispatch.yml@main
Comment thread
st3penta marked this conversation as resolved.
with:
event_action: ${{ github.event.action }}
install_mode: per-repo
mint_url: ${{ vars.FULLSEND_MINT_URL }}
gcp_region: ${{ vars.FULLSEND_GCP_REGION }}
project_number: ${{ vars.FULLSEND_PROJECT_NUMBER }}
runner_image: ubuntu-24.04
secrets:
FULLSEND_GCP_WIF_PROVIDER: ${{ secrets.FULLSEND_GCP_WIF_PROVIDER }}
FULLSEND_GCP_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
FULLSEND_OPENAI_API_KEY: ${{ secrets.FULLSEND_OPENAI_API_KEY }}
OTEL_EXPORTER_OTLP_TRACES_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_TRACES_HEADERS }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}

stop-fix:
# Job-level if: is intentionally coarse — it only screens for the
# /fs-fix-stop command on a PR from a non-bot. The authoritative
# authorization decision (collaborator permission API + PR-author escape
# hatch) is made in the step below, so a maintainer whose author_association
# is not MEMBER (e.g. private org membership) is not filtered out (ADR 0054).
if: >-
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.comment.user.type != 'Bot'
&& github.event.comment.body == '/fs-fix-stop'
&& (
github.event.comment.author_association == 'OWNER'
|| github.event.comment.author_association == 'MEMBER'
|| github.event.comment.author_association == 'COLLABORATOR'
|| github.event.comment.author_association == 'CONTRIBUTOR'
|| github.event.comment.user.login == github.event.issue.user.login
)
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: read
issues: write
Expand All @@ -69,7 +99,37 @@ jobs:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
COMMENT_USER_LOGIN: ${{ github.event.comment.user.login }}
ISSUE_USER_LOGIN: ${{ github.event.issue.user.login }}
run: |
set -euo pipefail
# ADR 0054: authorize via the collaborator permission API
# (admin|maintain|write), not author_association — the latter grants
# contributor status to anyone with a single merged PR (issue #5421).
# Mirrors has_repo_permission() in dispatch.yml; keep the two in sync.
# The PR author may always stop the fix agent on their own PR.
authorized=false
if [[ -n "$COMMENT_USER_LOGIN" && "$COMMENT_USER_LOGIN" == "$ISSUE_USER_LOGIN" ]]; then
authorized=true
else
if api_err=$(mktemp); then
if role=$(gh api "repos/$REPO/collaborators/$COMMENT_USER_LOGIN/permission" \
--jq '.role_name' 2>"$api_err"); then
case "$role" in
admin|maintain|write) authorized=true ;;
esac
else
echo "::warning::Permission API call failed for $COMMENT_USER_LOGIN: $(cat "$api_err")"
fi
rm -f "$api_err"
else
echo "::warning::Failed to create temp file for permission check of $COMMENT_USER_LOGIN"
fi
fi
if [[ "$authorized" != "true" ]]; then
echo "::notice::User $COMMENT_USER_LOGIN is not authorized to stop the fix agent (requires write access or PR authorship)"
exit 0
fi
gh label create "fullsend-no-fix" --repo "$REPO" \
--description "Skip bot-triggered fix agent runs" --color "FBCA04" \
--force 2>/dev/null || true
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/prioritize.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright The Conforma Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# This file is managed by fullsend. Do not edit it directly.
# Upstream: https://github.com/fullsend-ai/fullsend/blob/main/internal/scaffold/fullsend-repo/.github/workflows/prioritize.yml
---
# fullsend-stage: prioritize
name: Prioritize

permissions:
actions: write
contents: read
id-token: write
issues: write

on:
workflow_dispatch:
inputs:
event_type:
required: true
type: string
source_repo:
required: true
type: string
event_payload:
required: true
type: string
project_number:
description: GitHub Projects V2 project number for RICE scoring
required: false
type: string

concurrency:
group: fullsend-prioritize-${{ inputs.source_repo }}-${{ fromJSON(inputs.event_payload).issue.number }}
cancel-in-progress: true

jobs:
prioritize:
uses: fullsend-ai/fullsend/.github/workflows/reusable-prioritize.yml@main
with:
event_type: ${{ inputs.event_type }}
source_repo: ${{ inputs.source_repo }}
event_payload: ${{ inputs.event_payload }}
mint_url: ${{ vars.FULLSEND_MINT_URL }}
gcp_region: ${{ vars.FULLSEND_GCP_REGION }}
project_number: ${{ inputs.project_number || vars.FULLSEND_PROJECT_NUMBER }}
install_mode: per-repo
runner_image: ubuntu-24.04
secrets:
FULLSEND_GCP_WIF_PROVIDER: ${{ secrets.FULLSEND_GCP_WIF_PROVIDER }}
FULLSEND_GCP_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
FULLSEND_OPENAI_API_KEY: ${{ secrets.FULLSEND_OPENAI_API_KEY }}
OTEL_EXPORTER_OTLP_TRACES_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_TRACES_HEADERS }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
Loading
Loading