Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
9 commits
Select commit Hold shift + click to select a range
3924177
๋ณด์•ˆ ํ–ฅ์ƒ: CI ์Šคํฌ๋ฆฝํŠธ์˜ subprocess ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฐ ๋ฏผ๊ฐ ์ •๋ณด ์ œ๊ฑฐ
seonghobae Jun 29, 2026
48698aa
Merge remote-tracking branch 'origin/main' into pr-117
seonghobae Jun 29, 2026
983559f
๋ณด์•ˆ ํ–ฅ์ƒ: CI ์Šคํฌ๋ฆฝํŠธ์˜ subprocess ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฐ ๋ฏผ๊ฐ ์ •๋ณด ์ œ๊ฑฐ
seonghobae Jun 29, 2026
c9c017f
Resolve merge conflicts with origin/main
Copilot Jul 1, 2026
77dc0c1
Increase OpenCode model pool retry resilience
Copilot Jul 1, 2026
db69a32
๐Ÿ›ก๏ธ Sentinel: [๋ณด์•ˆ ํ–ฅ์ƒ] CI ์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์„ธ์Šค ์ถœ๋ ฅ ๋‚ด ๋ฏผ๊ฐ ์ •๋ณด ๋งˆ์Šคํ‚น ์ ์šฉ
seonghobae Jul 1, 2026
56a9a47
๐Ÿ›ก๏ธ Sentinel: [๋ณด์•ˆ ํ–ฅ์ƒ] CI ์Šคํฌ๋ฆฝํŠธ ์—๋Ÿฌ ๋กœ๊น… ๋ฐ ํ”„๋กœ์„ธ์Šค ์ถœ๋ ฅ ๋‚ด ๋ฏผ๊ฐ ์ •๋ณด ์œ ์ถœ ๋ฐฉ์ง€
seonghobae Jul 1, 2026
6da3a2e
๐Ÿ›ก๏ธ Sentinel: [๋ฒ„๊ทธ ์ˆ˜์ •] JSON ๋””์ฝ”๋”ฉ ์ค‘๋ณต ๋ฐฉ์ง€ (์„ฑ๋Šฅ ๋ฐ ๋™์ž‘ ๊ฐœ์„ )
seonghobae Jul 1, 2026
dd9cff9
๐Ÿ›ก๏ธ Sentinel: [๋ณด์•ˆ ํ–ฅ์ƒ] CI ์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์„ธ์Šค ์ถœ๋ ฅ ๋‚ด ๋ฏผ๊ฐ ์ •๋ณด ๋งˆ์Šคํ‚น ์ ์šฉ
seonghobae Jul 1, 2026
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
449 changes: 74 additions & 375 deletions .github/workflows/opencode-review.yml

Large diffs are not rendered by default.

130 changes: 0 additions & 130 deletions .github/workflows/pr-review-fix-scheduler.yml

This file was deleted.

35 changes: 9 additions & 26 deletions .github/workflows/pr-review-merge-scheduler.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
name: Required PR Review Merge Scheduler
name: PR Review Merge Scheduler

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
workflow_run:
workflows: ["Required OpenCode Review"]
types: [completed]
workflow_call:
inputs:
dry_run:
Expand Down Expand Up @@ -96,8 +93,8 @@ on:
default: "45"

concurrency:
group: central-pr-review-merge-scheduler-${{ github.repository }}-${{ github.event.pull_request.number || github.event.workflow_run.pull_requests[0].number || github.ref || github.run_id }}
cancel-in-progress: true
group: central-pr-review-merge-scheduler-${{ github.repository }}
cancel-in-progress: false

jobs:
scan-pr-queue:
Expand All @@ -114,33 +111,19 @@ jobs:
DRY_RUN: ${{ inputs.dry_run == true }}
MAX_PRS: ${{ inputs.max_prs || '100' }}
PROJECT_FLOW_INPUT: ${{ inputs.project_flow || vars.PROJECT_FLOW || '' }}
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || github.event.workflow_run.pull_requests[0].number || '' }}
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || '' }}
TRIGGER_REVIEWS: ${{ github.event_name == 'schedule' || github.event_name == 'pull_request_target' || inputs.trigger_reviews == true }}
ENABLE_AUTO_MERGE: ${{ github.event_name == 'schedule' || github.event_name == 'pull_request_target' || github.event_name == 'workflow_run' || inputs.enable_auto_merge == true }}
ENABLE_AUTO_MERGE: ${{ github.event_name == 'schedule' || github.event_name == 'pull_request_target' || inputs.enable_auto_merge == true }}
MERGE_MODE: ${{ inputs.merge_mode || vars.PR_MERGE_MODE || 'auto' }}
UPDATE_BRANCHES: ${{ github.event_name == 'schedule' || github.event_name == 'pull_request_target' || github.event_name == 'workflow_run' || inputs.update_branches == true }}
UPDATE_BRANCHES: ${{ github.event_name == 'schedule' || github.event_name == 'pull_request_target' || inputs.update_branches == true }}
STALE_OPENCODE_MINUTES: ${{ inputs.stale_opencode_minutes || vars.STALE_OPENCODE_MINUTES || '45' }}
CANONICAL_REF: ${{ inputs.canonical_ref || 'main' }}
steps:
- name: Resolve trusted scheduler source ref
id: trusted_source
env:
INPUT_CANONICAL_REF: ${{ inputs.canonical_ref || '' }}
WORKFLOW_REF: ${{ github.workflow_ref }}
run: |
set -euo pipefail
trusted_ref="${INPUT_CANONICAL_REF:-main}"
case "$WORKFLOW_REF" in
ContextualWisdomLab/.github/.github/workflows/pr-review-merge-scheduler.yml@*)
trusted_ref="${WORKFLOW_REF##*@}"
;;
esac
printf 'ref=%s\n' "$trusted_ref" >>"$GITHUB_OUTPUT"

- name: Checkout trusted scheduler
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
Comment on lines 122 to 124
repository: ContextualWisdomLab/.github
ref: ${{ steps.trusted_source.outputs.ref }}
ref: ${{ env.CANONICAL_REF }}
fetch-depth: 1

- name: Self-test scheduler
Expand All @@ -162,7 +145,7 @@ jobs:
--base-branch "$DEFAULT_BRANCH"
--max-prs "$MAX_PRS"
--project-flow "$project_flow"
--review-workflow "Required OpenCode Review"
--review-workflow "OpenCode Review"
--stale-opencode-minutes "$STALE_OPENCODE_MINUTES"
)
if [ -n "$PULL_REQUEST_NUMBER" ]; then
Expand Down
20 changes: 7 additions & 13 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ on:
description: Optional pull request number for trusted PR-scope evidence
required: false
type: string
target_repository:
description: Optional repository that owns the pull request, in owner/name form
required: false
default: ""
type: string
pr_base_sha:
description: Optional pull request base SHA for trusted PR-scope evidence
required: false
Expand All @@ -34,7 +29,7 @@ on:

concurrency:
group: >-
strix-${{ github.event.inputs.target_repository || github.repository }}-${{ github.event_name == 'pull_request_target' &&
strix-${{ github.repository }}-${{ github.event_name == 'pull_request_target' &&
format('pr-{0}-{1}', github.event.pull_request.number, github.event.pull_request.head.sha) ||
github.event.inputs.pr_number != '' && github.event.inputs.pr_head_sha != '' &&
format('pr-{0}-{1}', github.event.inputs.pr_number, github.event.inputs.pr_head_sha) ||
Expand Down Expand Up @@ -139,8 +134,8 @@ jobs:

- name: Materialize target workspace
env:
GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || github.token }}
REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.event.inputs.target_repository || github.repository }}
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
TARGET_WORKSPACE_SHA: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.sha }}
run: |
set -euo pipefail
Expand All @@ -159,7 +154,7 @@ jobs:
- name: Fetch pull request head for trusted scan
if: github.event_name == 'pull_request_target' || github.event.inputs.pr_number != ''
env:
GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || github.token }}
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.number || github.event.inputs.pr_number }}
PR_BASE_SHA: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.event.inputs.pr_base_sha }}
PR_HEAD_SHA: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.event.inputs.pr_head_sha }}
Expand Down Expand Up @@ -456,7 +451,7 @@ jobs:
STRIX_LLM_MAX_RETRIES: 1
STRIX_TRANSIENT_RETRY_PER_MODEL: 2
STRIX_TRANSIENT_RETRY_BACKOFF_SECONDS: 60
STRIX_FALLBACK_MODELS: ${{ steps.gate.outputs.provider_mode == 'github_models' && 'github_models/openai/gpt-5-chat github_models/openai/o3 github_models/deepseek/deepseek-v3-0324 github_models/deepseek/deepseek-r1-0528 github_models/deepseek/deepseek-r1' || '' }}
STRIX_FALLBACK_MODELS: ${{ steps.gate.outputs.provider_mode == 'github_models' && 'github_models/deepseek/deepseek-v3-0324 github_models/deepseek/deepseek-r1-0528' || '' }}
STRIX_FAIL_ON_PROVIDER_SIGNAL: "1"
STRIX_VERTEX_FALLBACK_MODELS: ""
NPM_CONFIG_IGNORE_SCRIPTS: "true"
Expand Down Expand Up @@ -524,8 +519,7 @@ jobs:
steps:
- name: Publish same-head manual Strix status
env:
GH_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN || github.token }}
TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }}
GH_TOKEN: ${{ github.token }}
PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }}
STRIX_RESULT: ${{ needs.strix.result }}
run: |
Expand All @@ -550,7 +544,7 @@ jobs:
;;
esac

gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
gh api -X POST "repos/${GITHUB_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
-f state="$state" \
-f context="strix" \
-f description="$description" \
Expand Down
3 changes: 0 additions & 3 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@
## 2024-11-20 - JSON Decoding Performance - Index Advancement
**Learning:** Even when avoiding string slicing using `json.JSONDecoder().raw_decode(text, index)`, failing to correctly advance the index by ignoring the returned `end` index (`value, _ = decoder.raw_decode(...)`) forces the search loop to repeatedly attempt to decode nested JSON structures (e.g., inner braces `{`) sequentially. This leads to massive O(N^2) time complexity and redundant parsing for large, deeply nested JSON objects.
**Action:** Always capture and use the new end index returned by `raw_decode` (e.g., `value, next_idx = decoder.raw_decode(text, index)`) to jump over the completely parsed object and proceed efficiently.
## 2026-06-25 - Avoid N+1 API blocking in PR checks
**Learning:** In backend processing scripts, synchronous iterations calling an external service, such as fetching `restMergeableState` per PR, cause N+1 API bottlenecks and stall pipeline execution linearly. This matters for PR schedulers handling multiple PRs.
**Action:** Use `concurrent.futures.ThreadPoolExecutor` for independent network calls in a loop, and bound `max_workers` to avoid API rate limits.
8 changes: 4 additions & 4 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
**Vulnerability:** Workflow CI Security Bypass / Markdown Injection
**Learning:** The GitHub Actions workflow `opencode-review.yml` attempted to optimize performance by doing a fast-path bash string extraction. If this succeeded, it skipped the Python JSON normalizer (`opencode_review_normalize_output.py`). This is a security flaw because the bash script does not escape `<, >, &` characters, allowing attackers to inject `-->` directly in JSON strings to break out of HTML comment sections.
**Prevention:** Removed the fast-path check entirely. We must always enforce JSON normalization via `opencode_review_normalize_output.py` because it correctly parses the JSON payload and safely escapes all characters as `\u003c`, `\u003e` and `\u0026`.
## 2026-06-25 - Prevent CI Logs Security Exposure and Explicit Shell Usage
**Vulnerability:** Information Disclosure / Command Injection
**Learning:** `subprocess.run` defaults to `shell=False`, but linters like Bandit require explicit `shell=False` to pass security checks. Furthermore, logging `process.stderr` or command arguments in CI tools can leak sensitive data (e.g., GitHub tokens or API keys passed to commands) if a command fails and dumps the context.
**Prevention:** Always explicitly define `shell=False` when using `subprocess.run()`. Scrub secrets from both arguments and `stderr` before including them in error messages within CI scripts.
## 2026-06-29 - Prevent Silent Failure by Capturing stderr in CI Scripts
**Vulnerability:** Silent Failure / Secret Leakage Risk
**Learning:** In `scripts/ci/opencode_review_approve_gate.sh`, `subprocess.run` dropped `stderr` entirely (`stderr=subprocess.DEVNULL`). This hides potential Git errors and causes maintainability regressions. Blindly logging `stderr` instead, however, risks leaking sensitive credentials injected by GitHub Actions.
**Prevention:** Capture `stderr` and filter out known credential patterns (e.g., Bearer tokens, GitHub PATs) before writing errors to `sys.stderr`. Never drop `stderr` completely on subprocess failures.
Loading
Loading