-
Notifications
You must be signed in to change notification settings - Fork 0
fix(ci): restore review control plane and respond to agent mentions #757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
75 commits
Select commit
Hold shift + click to select a range
bf16d27
feat(ci): route PR comment agent mentions
seonghobae 44a3afa
feat(ci): respond to review-agent mentions
seonghobae e9f223e
test(ci): cover review-agent mention routing
seonghobae 185d5ba
test(ci): load router module safely
seonghobae 225b266
test(ci): specify trusted comment routing contract
seonghobae c8e6ec1
test(ci): cover organization mention sweep
seonghobae 26ef319
test(ci): enforce mention workflow security contract
seonghobae 57e6291
feat(ci): route trusted mentions through central review events
seonghobae d3868f5
feat(ci): sweep organization PR comments for agent mentions
seonghobae 6f46a64
feat(ci): route local and organization-wide agent mentions
seonghobae 0db74c7
docs(ci): document review-agent comment invocation
seonghobae af29c2c
fix(ci): restore review and security baseline for comment routing
seonghobae 7dda47d
fix(ci): install validated Python locks atomically
seonghobae 17c196d
fix(ci): preserve lock preflight contract
seonghobae 1a29496
fix(ci): trust only automation receipt markers
seonghobae 0a838ec
fix(ci): bound and validate organization mention sweep
seonghobae bb9cc61
docs(ci): correct retrieval dates
seonghobae 0e62b10
fix(ci): scope local mention routing to central repository
seonghobae 437f054
test(ci): cover trusted receipt authorship
seonghobae 5d2b81b
test(ci): cover lazy and fail-closed mention sweep
seonghobae 4cd8ef3
test(ci): pin central repository gate
seonghobae e84486c
test(ci): prove aggregate Python lock installation
seonghobae 82c857a
fix(ci): redact subprocess commands and output
seonghobae 6bf63ed
fix(ci): redact sandbox verification evidence
seonghobae ba54e95
fix(ci): redact sandboxed web E2E evidence
seonghobae 3f81971
test(ci): cover sandbox evidence redaction
seonghobae c994f4e
docs(ci): document sandbox output redaction
seonghobae a2d6c13
fix(ci): consolidate runtime coverage and redaction boundaries
seonghobae 4508edf
docs(doctoring): replace superseded sandbox redaction record
seonghobae 8782eec
docs(changelog): record consolidated control-plane fixes
seonghobae 7913121
docs(doctoring): pin coverage semantics to Vitest 3.2.7
seonghobae a908eb0
fix(security): bound deeply nested JSON redaction
seonghobae c525596
test(security): prove fail-closed nested JSON redaction
seonghobae 9493a7d
docs(doctoring): record bounded deep JSON redaction
seonghobae aa1e0c9
docs(changelog): record fail-closed JSON depth handling
seonghobae 41e9253
fix(security): classify long assignments in one pass
seonghobae 5f3a4c4
test(security): verify one-pass long assignment handling
seonghobae 59b4f82
test(redaction): cover echoed separate secret options
seonghobae f39af5e
fix(security): redact concatenated credential key names
seonghobae 72a9ef6
test(security): cover concatenated sensitive JSON keys
seonghobae 538cd06
fix(redaction): scrub echoed separate secret options
seonghobae 84d2a1c
fix(security): fail closed for JSON-like diagnostic parse errors
seonghobae f295e5f
test(security): cover JSON-like and echoed option boundaries
seonghobae 6a05c29
docs(doctoring): fail closed on malformed JSON-like evidence
seonghobae 6153069
docs(changelog): record malformed structured evidence handling
seonghobae 50f75c6
test(ci): define exact-head control-plane quality contract
seonghobae f69b5b6
ci: add exact-head control-plane quality gate
seonghobae f664ac3
docs(doctoring): require exact-head control-plane quality evidence
seonghobae 0363abe
docs(changelog): add exact-head quality gate
seonghobae 7265fee
test(security): assert explicit non-shell subprocess execution
seonghobae 1bffbd7
fix(security): redact quoted echoed option values
seonghobae 25a929f
test(ci): require path-bounded dynamic coverage evidence
seonghobae 4127255
ci: measure dynamically loaded control-plane modules
seonghobae da65c18
test(ci): require isolated coverage configuration
seonghobae bafc089
ci: isolate exact-head coverage configuration
seonghobae c651531
test(ci): close exact-head branch coverage gaps
seonghobae a474985
fix(ci): execute complete control-plane coverage contracts
seonghobae 5a95ff2
test(ci): close central control-plane coverage edges
seonghobae e15356e
ci: execute complete control-plane coverage closure
seonghobae c01d1cd
fix(security): redact deep fallback credential assignments
seonghobae 5cdbc36
ci: diagnose exact-head control-plane coverage
seonghobae d12bd08
test(control-plane): capture exact-head coverage gaps
github-actions[bot] d66c2c2
ci: verify PR 757 exact-head quality repair
seonghobae e73c2e2
fix(control-plane): remove branch-selected manual router entrypoint
seonghobae db243a1
test(control-plane): cover package-qualified scheduler import fallback
seonghobae 59120ed
test(control-plane): require operable manual mention sweep
seonghobae 48cdc28
fix(control-plane): close credential redaction parser gaps
seonghobae c22f614
test(control-plane): isolate ownership-boundary fixture
seonghobae 40b4a92
fix(control-plane): restore manual mention sweep
seonghobae 47f6ba5
test(control-plane): distinguish trusted manual sweep from branch sel…
seonghobae 29b1fd4
chore(control-plane): remove transient coverage diagnosis
seonghobae 0a5501e
chore(control-plane): remove unused one-shot repair workflow
seonghobae 337f426
test(control-plane): close redaction and import fallback coverage
seonghobae 8d9232a
ci(pr757): focus agent mention router on current main
seonghobae 548bb41
chore(ci): remove write-capable PR 757 focus workflow
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| name: Review Agent Mention Router | ||
|
|
||
| on: | ||
| issue_comment: | ||
| types: [created] | ||
| schedule: | ||
| - cron: "*/5 * * * *" | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: review-agent-mention-router-${{ github.repository }} | ||
| cancel-in-progress: false | ||
|
|
||
| # Organization required-workflow rules do not propagate issue_comment events | ||
| # into sibling repositories. Keep the workflow default read-only; each bounded | ||
| # job declares only the writes it actually needs. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| route-local-agent-mention: | ||
| if: >- | ||
| github.repository == 'ContextualWisdomLab/.github' | ||
| && github.event_name == 'issue_comment' | ||
| && github.event.issue.pull_request | ||
| && github.event.comment.user.type != 'Bot' | ||
| && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) | ||
| && ( | ||
| contains(github.event.comment.body, '@cwl-noema-review') | ||
| || contains(github.event.comment.body, '@opencode-agent') | ||
| ) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| permissions: | ||
| contents: write | ||
| issues: write | ||
| pull-requests: read | ||
| env: | ||
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | ||
| GH_TOKEN: ${{ github.token }} | ||
| TARGET_REPOSITORY_TOKEN: ${{ github.token }} | ||
| AGENT_DISPATCH_TOKEN: ${{ github.token }} | ||
| OPENCODE_REPOSITORY_DISPATCH_TARGETS: ${{ vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS }} | ||
| steps: | ||
| - name: Check out trusted default-branch router | ||
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | ||
| with: | ||
| ref: ${{ github.event.repository.default_branch }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Resolve immutable pull-request head and prior receipts | ||
| env: | ||
| REPOSITORY: ${{ github.repository }} | ||
| PR_NUMBER: ${{ github.event.issue.number }} | ||
| SOURCE_EVENT_PATH: ${{ github.event_path }} | ||
| run: | | ||
| set -euo pipefail | ||
| pr_json="$(gh api "repos/${REPOSITORY}/pulls/${PR_NUMBER}")" | ||
| comments_json="$( | ||
| gh api --paginate --slurp \ | ||
| "repos/${REPOSITORY}/issues/${PR_NUMBER}/comments?per_page=100" \ | ||
| | jq -c 'add // []' | ||
| )" | ||
| jq \ | ||
| --argjson pull_request "$pr_json" \ | ||
| --argjson conversation_comments "$comments_json" \ | ||
| '. + { | ||
| pull_request: $pull_request, | ||
| conversation_comments: $conversation_comments | ||
| }' \ | ||
| "$SOURCE_EVENT_PATH" >"${RUNNER_TEMP}/agent-mention-event.json" | ||
|
|
||
| - name: Route trusted local agent mention | ||
| run: >- | ||
| python3 scripts/ci/agent_mention_router.py | ||
| --event-path "${RUNNER_TEMP}/agent-mention-event.json" | ||
|
|
||
| sweep-organization-agent-mentions: | ||
| if: >- | ||
| github.repository == 'ContextualWisdomLab/.github' | ||
| && ( | ||
| github.event_name == 'schedule' | ||
| || github.event_name == 'workflow_dispatch' | ||
| ) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| permissions: | ||
| contents: write | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
| id-token: write | ||
| env: | ||
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | ||
| OPENCODE_REPOSITORY_DISPATCH_TARGETS: ${{ vars.OPENCODE_REPOSITORY_DISPATCH_TARGETS }} | ||
| LOOKBACK_HOURS: ${{ vars.AGENT_MENTION_LOOKBACK_HOURS || '168' }} | ||
| MAX_DISPATCHES: ${{ vars.AGENT_MENTION_MAX_DISPATCHES || '20' }} | ||
| DRY_RUN: "false" | ||
| steps: | ||
| - name: Exchange OpenCode app token for sibling-repository comments | ||
| id: sweep_app_token | ||
| env: | ||
| OIDC_AUDIENCE: opencode-github-action | ||
| OPENCODE_API_BASE_URL: https://api.opencode.ai | ||
| USER_TOKEN_CONFIGURED: ${{ secrets.PR_REVIEW_MERGE_TOKEN != '' || secrets.OPENCODE_APPROVE_TOKEN != '' }} | ||
| run: | | ||
| set -euo pipefail | ||
| mark_unavailable() { | ||
| echo "available=false" >>"$GITHUB_OUTPUT" | ||
| } | ||
| if [ "$USER_TOKEN_CONFIGURED" = "true" ]; then | ||
| echo "A configured cross-repository user token takes precedence." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then | ||
| echo "OpenCode app token exchange unavailable: OIDC request environment is missing." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}" | ||
| separator="&" | ||
| case "$request_url" in | ||
| *\?*) ;; | ||
| *) separator="?" ;; | ||
| esac | ||
| if ! oidc_response="$( | ||
| curl -fsS \ | ||
| -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ | ||
| "${request_url}${separator}audience=${OIDC_AUDIENCE}" | ||
| )"; then | ||
| echo "OpenCode app token exchange unavailable: OIDC token request did not complete." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")" | ||
| if [ -z "$oidc_token" ]; then | ||
| echo "OpenCode app token exchange unavailable: OIDC token response was empty." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| if ! token_response="$( | ||
| curl -fsS \ | ||
| -X POST \ | ||
| -H "Authorization: Bearer ${oidc_token}" \ | ||
| "${OPENCODE_API_BASE_URL}/exchange_github_app_token" | ||
| )"; then | ||
| echo "OpenCode app token exchange unavailable: app token request did not complete." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| app_token="$(jq -r '.token // empty' <<<"$token_response")" | ||
| if [ -z "$app_token" ]; then | ||
| echo "OpenCode app token exchange unavailable: app token response was empty." | ||
| mark_unavailable | ||
| exit 0 | ||
| fi | ||
| echo "::add-mask::$app_token" | ||
| { | ||
| echo "available=true" | ||
| echo "token=$app_token" | ||
| } >>"$GITHUB_OUTPUT" | ||
|
|
||
| - name: Check out trusted central router | ||
| uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | ||
| with: | ||
| ref: ${{ github.event.repository.default_branch }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Sweep recent organization PR comments | ||
| env: | ||
| TARGET_REPOSITORY_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.sweep_app_token.outputs.token }} | ||
| TARGET_REPOSITORY_SOURCE: ${{ (secrets.PR_REVIEW_MERGE_TOKEN != '' || secrets.OPENCODE_APPROVE_TOKEN != '') && 'organization' || steps.sweep_app_token.outputs.available == 'true' && 'installation' || '' }} | ||
| AGENT_DISPATCH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [ -z "${TARGET_REPOSITORY_TOKEN:-}" ] || [ -z "${TARGET_REPOSITORY_SOURCE:-}" ]; then | ||
| echo "::error::Agent mention sweep requires PR_REVIEW_MERGE_TOKEN, OPENCODE_APPROVE_TOKEN, or the OpenCode app token exchange." | ||
| exit 1 | ||
| fi | ||
| args=( | ||
| --organization ContextualWisdomLab | ||
| --repository-source "$TARGET_REPOSITORY_SOURCE" | ||
| --lookback-hours "$LOOKBACK_HOURS" | ||
| --max-dispatches "$MAX_DISPATCHES" | ||
| ) | ||
| if [ "$DRY_RUN" = "true" ]; then | ||
| args+=(--dry-run) | ||
| fi | ||
| python3 scripts/ci/agent_mention_sweep.py "${args[@]}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.