Conversation
- Add issue templates (bug report, feature request, org setup) - Add PR template with BlackRoad-specific sections - Add CODE_OF_CONDUCT.md (Contributor Covenant 2.1) - Add CONTRIBUTING.md with org-specific guidelines - Add SECURITY.md with vulnerability reporting process - Add SUPPORT.md with help resources - Add CODEOWNERS for code review assignments - Add dependabot.yml for automated dependency updates - Add FUNDING.yml placeholder - Add .gitignore for common artifacts Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add CONTRIBUTORS.md for recognizing contributors - Add CHANGELOG.md with initial release notes - Add .github/README.md explaining GitHub automation - Add root README.md as main landing page Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Document Session 3: GitHub repository setup - Add all new files to session history - Mark GitHub repository setup as complete Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add CLAUDE_CODE_API.md with best practices, examples, and guidelines - Update INTEGRATIONS.md with detailed Anthropic/Claude API info - Update MEMORY.md to explicitly reference Claude Code API - Add Claude Code API badge to README.md - Enhance AI stack information in README.md - Update ai-router template with Claude Code API reference - Add AI-assisted development section to CONTRIBUTING.md - Update INDEX.md with Claude Code API link - Document changes in CHANGELOG.md Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add pytest configuration (pytest.ini) - Add test dependencies (requirements-test.txt) - Create tests/ directory with shared fixtures (conftest.py) - Add 73 passing tests for Operator prototype: - 23 tests for parser.py (input parsing) - 24 tests for classifier.py (pattern matching) - 26 tests for router.py (routing logic) - Achieve 75% code coverage for Operator - All tests passing successfully Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add GitHub Actions workflow for automated testing (tests.yml) - Add comprehensive TESTING.md documentation - Update .gitignore with test artifacts - Update INDEX.md with TESTING.md link - Update CHANGELOG.md with testing infrastructure - All 73 tests passing with 75% coverage Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Document Session 4: Testing Infrastructure - Mark testing infrastructure as complete in Active Threads - Add details about 73 tests, 75% coverage, CI/CD Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add GitHub Actions workflow (auto-merge.yml) - Auto-merge PRs from copilot/** branches when checks pass - Support auto-merge label for other branches - Add eligibility checking (checks passed, no conflicts, not draft) - Use squash merge strategy - Add PR comments with merge status - Create AUTO_MERGE.md comprehensive documentation - Update README.md with auto-merge badge - Update INDEX.md with AUTO_MERGE.md link - Update CHANGELOG.md with auto-merge feature - Update MEMORY.md with Session 5 details Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Add 24 comprehensive tests for Control Plane - Test Bridge core functionality (state, status, routing) - Test organization and template listing - Test signal emission, search, and browsing - Test lazy loading of components - Fix Bridge.browse() to use correct Explorer API - Fix Bridge.signal() to use simple format - Fix Bridge.search() to return dict results directly - All 97 tests passing (73 operator + 24 control plane) - 73% overall code coverage Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
- Update MEMORY.md with Session 6 (Control Plane testing) - Mark Control Plane as DONE in Active Threads - Update CHANGELOG.md with Control Plane validation - Update test count in README (97 tests passing) - Update Active Threads numbering - Document 73% overall coverage Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
…ocumentation Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Sync Active Threads section with .STATUS - mark threads 7-12 as DONE: - Control plane CLI (prototypes/control-plane) - Node configs (all 7 nodes) - GitHub Actions (8 workflows) - Webhook handlers (prototypes/webhooks) - MCP Server (prototypes/mcp-server) - Dispatcher (prototypes/dispatcher) https://claude.ai/code/session_01JzfHdbRffmyB7hY3Sagjyt
Pulled from BlackRoad-OS repos: - agents/README.md - Registry of 1,050 agents across 20 types - agents/types.yaml - Detailed type definitions with capabilities - agents/ORCHESTRATION.md - Swarm coordination patterns - EMOJI_DICTIONARY.md - Visual language reference from blackroad-docs Updated INDEX.md with new Agents section and emoji dictionary link. https://claude.ai/code/session_01JzfHdbRffmyB7hY3Sagjyt
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Provides a single-file reference covering repository structure, development workflows, conventions, architecture, and session startup checklist for any AI assistant working in The Bridge. https://claude.ai/code/session_01JWYQzDR5tuCTFS2X3YPi5t
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com>
# Conflicts: # CODE_OF_CONDUCT.md # CONTRIBUTING.md # INDEX.md # README.md # SECURITY.md
# Conflicts: # README.md
# Conflicts: # .github/workflows/auto-merge.yml # README.md
…-GkZQ0' # Conflicts: # INDEX.md # MEMORY.md
| PR_NUMBER="${{ github.event.pull_request.number }}" | ||
| elif [ "${{ github.event_name }}" == "workflow_run" ]; then | ||
| # Extract PR number from workflow run | ||
| PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="${{ github.event.workflow_run.head_branch }}") | .number' | head -1) |
Check failure
Code scanning / CodeQL
Code injection Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
In general, to fix this class of problem in GitHub Actions, untrusted expressions like ${{ github.* }} or ${{ inputs.* }} should not be injected directly into run: scripts where they will be interpreted by a shell or another language (jq, JavaScript, etc.). Instead, assign the expression to an environment variable via env: (or with.env:) and then reference it using the native variable syntax of the target interpreter ($VAR in bash, process.env.VAR in Node, etc.). This prevents the expression language from being evaluated again inside the script and reduces the risk of code injection.
For this workflow, the vulnerable use is on line 41 where ${{ github.event.workflow_run.head_branch }} is interpolated directly into the jq expression inside the shell script. The safest fix without changing functionality is:
- Define an environment variable (e.g.,
HEAD_BRANCH) for the job or at least for the “Get PR info” step, assigning it${{ github.event.workflow_run.head_branch }}. - Use standard shell variable expansion to insert
$HEAD_BRANCHinto the jq filter string, still within single quotes, so jq sees the correct branch name while the shell does not interpret its contents. - Optionally handle the case where
HEAD_BRANCHmay be empty (for non-workflow_run events), but that can be left as-is since current logic only uses the jq command in theworkflow_runbranch.
Concretely, in .github/workflows/auto-merge.yml, update the “Get PR info” step to include HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} under env:. Then, replace the jq invocation on line 41 from:
PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="${{ github.event.workflow_run.head_branch }}") | .number' | head -1)to:
PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="'"$HEAD_BRANCH"'") | .number' | head -1)This uses shell-safe concatenation of single- and double-quoted strings so that $HEAD_BRANCH is expanded by the shell, but its contents are not reinterpreted by the shell, and jq still receives a proper string literal.
| @@ -32,13 +32,14 @@ | ||
| id: pr | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | ||
| run: | | ||
| # Get PR number from the event | ||
| if [ "${{ github.event_name }}" == "pull_request_review" ]; then | ||
| PR_NUMBER="${{ github.event.pull_request.number }}" | ||
| elif [ "${{ github.event_name }}" == "workflow_run" ]; then | ||
| # Extract PR number from workflow run | ||
| PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="${{ github.event.workflow_run.head_branch }}") | .number' | head -1) | ||
| PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="'"$HEAD_BRANCH"'") | .number' | head -1) | ||
| else | ||
| echo "No PR found for event type: ${{ github.event_name }}" | ||
| exit 1 |
| fi | ||
|
|
||
| if [ -z "$PR_NUMBER" ]; then | ||
| echo "No PR number found for branch ${{ github.event.workflow_run.head_branch }}" |
Check failure
Code scanning / CodeQL
Code injection Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
To fix the problem, the untrusted value (github.event.workflow_run.head_branch) should not be interpolated directly into the shell within the run: block using ${{ ... }}. Instead, it should be passed into the step via env: and then referenced inside the script using normal shell variable syntax like $HEAD_BRANCH. This breaks the direct templating-to-shell path that enables code injection.
Concretely, for the “Get PR info” step in .github/workflows/auto-merge.yml, we should:
- Add an environment variable, e.g.
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}underenv:. - Replace usages of
${{ github.event.workflow_run.head_branch }}inside therun:script with$HEAD_BRANCH. - Keep existing behavior the same: the variable is only used to match PRs by head ref and to print an error message.
We must only edit within the shown snippet of .github/workflows/auto-merge.yml. Specifically:
- Around lines 33–35, extend the
env:mapping to includeHEAD_BRANCHwith the expression. - At line 41, change the
gh pr listcommand so thatselect(.headRefName=="${{ github.event.workflow_run.head_branch }}")becomesselect(.headRefName=="'$HEAD_BRANCH'")or equivalent safe quoting. The simplest is to replace the interpolated expression with$HEAD_BRANCHand keep the surrounding double quotes, resulting inselect(.headRefName=="$HEAD_BRANCH"). - At line 48, change the error message from
branch ${{ github.event.workflow_run.head_branch }}tobranch $HEAD_BRANCH.
No new methods or external libraries are needed; we only adjust YAML env: and shell variable usage in the existing step.
| @@ -32,20 +32,21 @@ | ||
| id: pr | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | ||
| run: | | ||
| # Get PR number from the event | ||
| if [ "${{ github.event_name }}" == "pull_request_review" ]; then | ||
| PR_NUMBER="${{ github.event.pull_request.number }}" | ||
| elif [ "${{ github.event_name }}" == "workflow_run" ]; then | ||
| # Extract PR number from workflow run | ||
| PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="${{ github.event.workflow_run.head_branch }}") | .number' | head -1) | ||
| PR_NUMBER=$(gh pr list --json number,headRefName --jq '.[] | select(.headRefName=="'"$HEAD_BRANCH"'") | .number' | head -1) | ||
| else | ||
| echo "No PR found for event type: ${{ github.event_name }}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -z "$PR_NUMBER" ]; then | ||
| echo "No PR number found for branch ${{ github.event.workflow_run.head_branch }}" | ||
| echo "No PR number found for branch $HEAD_BRANCH" | ||
| exit 1 | ||
| fi | ||
|
|
| - name: Check merge conditions | ||
| id: check | ||
| run: | | ||
| STATE="${{ steps.pr.outputs.state }}" |
Check failure
Code scanning / CodeQL
Code injection Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
General fix: Avoid inserting untrusted data into a shell script via GitHub expression interpolation inside run:. Instead, assign the untrusted value to an environment variable using ${{ ... }} in the env: block, and then reference it inside run: using the shell’s native variable syntax ($VAR), which prevents it from being parsed by the Actions expression engine within the script.
Concrete changes here:
- In the
Check merge conditionsstep (lines 68–76), move the three${{ steps.pr.outputs.* }}expressions from therun:script into anenv:block:- Add
env:withSTATE,MERGEABLE, andREVIEW_DECISIONset from${{ steps.pr.outputs.state }},${{ steps.pr.outputs.mergeable }},${{ steps.pr.outputs.review_decision }}.
- Add
- Inside the
run:block, replace:STATE="${{ steps.pr.outputs.state }}"MERGEABLE="${{ steps.pr.outputs.mergeable }}"REVIEW_DECISION="${{ steps.pr.outputs.review_decision }}"
with simple shell assignments from the environment:STATE="$STATE"MERGEABLE="$MERGEABLE"REVIEW_DECISION="$REVIEW_DECISION"
- No new methods or imports are required; all changes are confined to the YAML workflow and this single step.
This preserves the existing logic and behavior while following the recommended pattern to avoid code injection issues.
| @@ -66,10 +66,14 @@ | ||
|
|
||
| - name: Check merge conditions | ||
| id: check | ||
| env: | ||
| STATE: ${{ steps.pr.outputs.state }} | ||
| MERGEABLE: ${{ steps.pr.outputs.mergeable }} | ||
| REVIEW_DECISION: ${{ steps.pr.outputs.review_decision }} | ||
| run: | | ||
| STATE="${{ steps.pr.outputs.state }}" | ||
| MERGEABLE="${{ steps.pr.outputs.mergeable }}" | ||
| REVIEW_DECISION="${{ steps.pr.outputs.review_decision }}" | ||
| STATE="$STATE" | ||
| MERGEABLE="$MERGEABLE" | ||
| REVIEW_DECISION="$REVIEW_DECISION" | ||
|
|
||
| echo "PR State: $STATE" | ||
| echo "Mergeable: $MERGEABLE" |
| id: check | ||
| run: | | ||
| STATE="${{ steps.pr.outputs.state }}" | ||
| MERGEABLE="${{ steps.pr.outputs.mergeable }}" |
Check failure
Code scanning / CodeQL
Code injection Critical
Copilot Autofix
AI 11 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
| run: | | ||
| STATE="${{ steps.pr.outputs.state }}" | ||
| MERGEABLE="${{ steps.pr.outputs.mergeable }}" | ||
| REVIEW_DECISION="${{ steps.pr.outputs.review_decision }}" |
Check failure
Code scanning / CodeQL
Code injection Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
General approach: Avoid using ${{ ... }} expressions directly inside shell scripts. Instead, set the potentially-untrusted value into an environment variable at the step level using GitHub expression syntax, and then reference that variable within the script using normal shell variable expansion ($VAR). This removes the direct interpolation path that CodeQL flags and follows GitHub’s recommended pattern.
Best concrete fix here:
- In the "Check merge conditions" step (lines 68–73), move the three interpolations (
${{ steps.pr.outputs.state }},mergeable, andreview_decision) from inside therun:script into anenv:block. - Inside the script, simply read them as
$STATE,$MERGEABLE, and$REVIEW_DECISIONwithout any${{ ... }}usage. - This addresses the flagged
review_decisionusage and, for consistency, hardens the other two values in the same way. - No new imports or external dependencies are required; this is purely a YAML/workflow change inside
.github/workflows/auto-merge.yml.
Concretely:
- Edit the
Check merge conditionsstep starting at line 68. - Add an
env:section under that step with:STATE: ${{ steps.pr.outputs.state }}MERGEABLE: ${{ steps.pr.outputs.mergeable }}REVIEW_DECISION: ${{ steps.pr.outputs.review_decision }}
- Replace the first three lines of the script body (70–72) with simple shell assignments that copy from the environment (
STATE="$STATE"etc.), or even just rely directly on the environment variables without reassigning; to keep minimal logic change, we’ll keep explicit assignments that no longer use${{ ... }}.
No other parts of the file need to change for this alert.
| @@ -66,10 +66,14 @@ | ||
|
|
||
| - name: Check merge conditions | ||
| id: check | ||
| env: | ||
| STATE: ${{ steps.pr.outputs.state }} | ||
| MERGEABLE: ${{ steps.pr.outputs.mergeable }} | ||
| REVIEW_DECISION: ${{ steps.pr.outputs.review_decision }} | ||
| run: | | ||
| STATE="${{ steps.pr.outputs.state }}" | ||
| MERGEABLE="${{ steps.pr.outputs.mergeable }}" | ||
| REVIEW_DECISION="${{ steps.pr.outputs.review_decision }}" | ||
| STATE="$STATE" | ||
| MERGEABLE="$MERGEABLE" | ||
| REVIEW_DECISION="$REVIEW_DECISION" | ||
|
|
||
| echo "PR State: $STATE" | ||
| echo "Mergeable: $MERGEABLE" |
| echo "🎯 Auto-merge Summary" | ||
| echo "" | ||
| echo "PR: #${{ steps.pr.outputs.pr_number }}" | ||
| echo "State: ${{ steps.pr.outputs.state }}" |
Check failure
Code scanning / CodeQL
Code injection Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
To fix this, avoid using ${{ steps.pr.outputs.state }} directly inside the run: script. Instead, assign the potentially tainted expression to an environment variable via the env: section of the step, and then reference it using native shell syntax ($PR_STATE) inside the script. This is the recommended pattern to prevent code injection in GitHub Actions, because the shell never sees the ${{ ... }} interpolation and only receives values as regular environment variables.
Concretely, in the Summary step (lines 121–129), add an env: block that exposes the needed outputs as environment variables: PR_NUMBER, PR_STATE, and CAN_MERGE. Then, in the run: block, replace echo "PR: #${{ steps.pr.outputs.pr_number }}", echo "State: ${{ steps.pr.outputs.state }}", and echo "Can merge: ${{ steps.check.outputs.can_merge }}" with shell variable references: echo "PR: #$PR_NUMBER", echo "State: $PR_STATE", and echo "Can merge: $CAN_MERGE". This change is local to .github/workflows/auto-merge.yml, preserves the existing functionality and output format, and removes the direct use of the tainted expression inside the script.
| @@ -120,10 +120,15 @@ | ||
|
|
||
| - name: Summary | ||
| if: always() | ||
| env: | ||
| PR_NUMBER: ${{ steps.pr.outputs.pr_number }} | ||
| PR_STATE: ${{ steps.pr.outputs.state }} | ||
| CAN_MERGE: ${{ steps.check.outputs.can_merge }} | ||
| JOB_STATUS: ${{ job.status }} | ||
| run: | | ||
| echo "🎯 Auto-merge Summary" | ||
| echo "" | ||
| echo "PR: #${{ steps.pr.outputs.pr_number }}" | ||
| echo "State: ${{ steps.pr.outputs.state }}" | ||
| echo "Can merge: ${{ steps.check.outputs.can_merge }}" | ||
| echo "Status: ${{ job.status }}" | ||
| echo "PR: #$PR_NUMBER" | ||
| echo "State: $PR_STATE" | ||
| echo "Can merge: $CAN_MERGE" | ||
| echo "Status: $JOB_STATUS" |
| name: Run Tests | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ['3.11', '3.12'] | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Python ${{ matrix.python-version }} | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| cache: 'pip' | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -r requirements-test.txt | ||
|
|
||
| - name: Run pytest | ||
| run: | | ||
| python -m pytest tests/ \ | ||
| --verbose \ | ||
| --cov=prototypes \ | ||
| --cov-report=term-missing \ | ||
| --cov-report=xml \ | ||
| --cov-report=html \ | ||
| -ra | ||
|
|
||
| - name: Upload coverage to Codecov | ||
| uses: codecov/codecov-action@v4 | ||
| if: matrix.python-version == '3.12' | ||
| with: | ||
| files: ./coverage.xml | ||
| flags: unittests | ||
| name: codecov-umbrella | ||
| fail_ci_if_error: false | ||
|
|
||
| - name: Archive coverage results | ||
| uses: actions/upload-artifact@v4 | ||
| if: matrix.python-version == '3.12' | ||
| with: | ||
| name: coverage-report | ||
| path: htmlcov/ | ||
| retention-days: 30 | ||
|
|
||
| - name: Test Summary | ||
| if: always() | ||
| run: | | ||
| echo "## Test Results 🧪" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "Python ${{ matrix.python-version }}" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | ||
| python -m pytest tests/ --quiet --tb=no || true | ||
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | ||
|
|
||
| lint: |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
In general, the fix is to explicitly declare a permissions block that limits the GITHUB_TOKEN to only the scopes needed. For a CI workflow that only needs to read the repository contents and upload artifacts/coverage, contents: read is usually sufficient. This can be set at the root of the workflow (affecting all jobs) or per-job; here, a single root-level permissions block is cleaner since both jobs have the same needs.
For this specific workflow, no step performs write operations to the repository, issues, or pull requests. actions/checkout, codecov/codecov-action, and actions/upload-artifact work with a read-only contents permission when they only need to read the code and upload data to external or GitHub-managed storage. Therefore, the best minimal change is to add:
permissions:
contents: readat the top level, between name: Tests and on:. This documents and enforces read-only repository access for all jobs without altering any existing steps or behavior.
Changes needed:
- Edit
.github/workflows/tests.yml. - Insert a new
permissionsblock after line 2 (name: Tests) and before line 4 (on:). - No new imports or methods are required; this is purely a YAML workflow configuration change.
| @@ -1,5 +1,7 @@ | ||
| # Run BlackRoad tests on pull requests and pushes | ||
| name: Tests | ||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| push: |
| -ra | ||
|
|
||
| - name: Upload coverage to Codecov | ||
| uses: codecov/codecov-action@v4 |
Check warning
Code scanning / CodeQL
Unpinned tag for a non-immutable Action in workflow Medium test
| name: Code Quality | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
| cache: 'pip' | ||
|
|
||
| - name: Install linting tools | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install black ruff mypy | ||
|
|
||
| - name: Check code formatting with Black | ||
| run: | | ||
| black --check --diff prototypes/ tests/ || true | ||
|
|
||
| - name: Lint with Ruff | ||
| run: | | ||
| ruff check prototypes/ tests/ || true | ||
| continue-on-error: true | ||
|
|
||
| - name: Type check with mypy | ||
| run: | | ||
| mypy prototypes/ --ignore-missing-imports || true | ||
| continue-on-error: true |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 11 days ago
In general, fix this by adding an explicit permissions: block that grants only the minimal needed scopes. Since this workflow only checks out code, installs dependencies, runs tests, uploads coverage to Codecov, and uploads artifacts, it only needs read access to repository contents. It does not need to write to contents, pull requests, or issues.
The best fix without changing existing functionality is to add a permissions: block at the workflow root (right after name: Tests). This will apply to both test and lint jobs, satisfying the CodeQL recommendation and documenting required permissions. Set contents: read, which is the standard minimal scope for typical CI jobs that only need to read the repository.
Concretely, in .github/workflows/tests.yml, between line 2 (name: Tests) and line 4 (on:), insert:
permissions:
contents: readNo additional methods, imports, or other definitions are needed.
| @@ -1,5 +1,7 @@ | ||
| # Run BlackRoad tests on pull requests and pushes | ||
| name: Tests | ||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| push: |
There was a problem hiding this comment.
Pull request overview
This PR establishes the initial project structure and testing infrastructure for the BlackRoad ecosystem. The changes include comprehensive test suites for core components, workflow automation for syncing updates across organizations, and an extensive agent-based development environment with 5 specialized AI agents using open-source models.
Changes:
- Added comprehensive testing infrastructure with 97 passing tests across operator and control plane prototypes
- Implemented sync-to-orgs workflow for automatically distributing updates to target repositories
- Created auto-merge workflow for approved PRs after CI passes
- Added agent-based codespace with 5 AI agents (coder, designer, ops, docs, analyst) using 7 open-source models
- Established session management system for agent collaboration and shared memory
Reviewed changes
Copilot reviewed 95 out of 122 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_sync.py | Test suite validating sync workflow functionality and registry configuration |
| tests/test_integration.py | Integration tests simulating complete sync flow without actual dispatch |
| tests/operator/test_parser.py | Comprehensive parser tests for various input types (text, HTTP, webhook, signal, CLI) |
| tests/operator/test_classifier.py | Classification tests for routing queries to appropriate organizations |
| tests/conftest.py | Shared pytest fixtures and test configuration |
| .github/workflows/sync-to-orgs.yml | Workflow for dispatching updates to active organization repositories |
| .github/workflows/auto-merge.yml | Automated PR merging after approval and CI success |
| .github/workflows/ci.yml | Enhanced CI with sync testing |
| pytest.ini | Pytest configuration with coverage and markers |
| requirements-test.txt | Testing infrastructure dependencies |
| docs/SYNC.md | Comprehensive documentation for sync functionality |
| codespace-agents/* | Agent orchestration, configuration, and deployment files |
| prototypes/sessions/* | Session management, collaboration, and shared memory implementations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Explorer just has tree() method | ||
| return self.explorer.tree() |
There was a problem hiding this comment.
The comment states that Explorer 'just has tree() method', but this contradicts the removed code which was calling show(path). If the Explorer API was intentionally changed to only support tree() without path-based navigation, this should be documented in the Explorer module itself or in a changelog to help other developers understand why the functionality was removed.
| # Use simple fallback format since SignalEmitter needs different args | ||
| return f"📡 OS → {target} : {message}" |
There was a problem hiding this comment.
The comment indicates that SignalEmitter exists but requires different arguments than what's available here. This hardcoded fallback format bypasses the actual SignalEmitter implementation, creating potential inconsistency in signal formatting across the codebase. Consider either: 1) updating SignalEmitter to accept these arguments, or 2) documenting the expected SignalEmitter interface so callers can provide the correct arguments.
There was a problem hiding this comment.
💡 Codex Review
.github/prototypes/dispatcher/dispatcher/core.py
Lines 156 to 158 in 8bfe5b5
When classification is missing, the dispatcher always falls back to default_services (here, crm for FND) and ignores the matched_service returned by Registry.match. That means queries that match explicit routing rules (e.g., salesforce → service salesforce, stripe|billing|payment → service stripe in routes/registry.yaml lines 542-550) will be sent to the org’s default service instead of the rule’s service whenever the operator is unavailable or classification fails. This breaks the rule-based routing that the registry is defining and will misroute requests to the wrong endpoint.
.github/.github/workflows/ci.yml
Lines 62 to 63 in 8bfe5b5
The Run operator tests step appends || echo "No tests yet", which converts any pytest failure into a success. That means legitimate test failures (not just “no tests collected”) will still allow the CI workflow to pass, enabling merges with broken operator behavior. If the intent is only to tolerate empty test suites, you’ll need a conditional that distinguishes pytest’s "no tests" exit code from real failures.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
No description provided.