Skip to content

chore: refresh org SBOM inventory - #1678

Open
opencode-agent[bot] wants to merge 102 commits into
mainfrom
automation/sbom-inventory
Open

chore: refresh org SBOM inventory#1678
opencode-agent[bot] wants to merge 102 commits into
mainfrom
automation/sbom-inventory

Conversation

@opencode-agent

@opencode-agent opencode-agent Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Automated central SBOM inventory refresh for live non-fork repositories. Review reciprocal, restricted, and NOASSERTION license evidence in docs/sbom/inventory.md against the product's actual distribution and hosted-service model.


Devin Review

@opencode-agent
opencode-agent Bot requested a review from seonghobae as a code owner September 2, 2026 04:27

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 3 potential issues.

⚠️ 3 issues in files not directly in the diff

⚠️ Partial inventory appears complete

With 34 of 63 SBOM fetches returning 404, repo_count reports all 63 while component totals cover only 29. The inventory presents partial organization evidence as complete.


⚠️ Permitted licenses trigger violations

For MPL-2.0 components without another prohibited license, flagged reports at least 137 policy violations. Governance therefore escalates expressly permitted dependencies.


⚠️ Permissive alternatives trigger violations

When an SPDX expression offers a permissive alternative, flagged rejects it because another alternative is copyleft. Seven selectable permissive dependencies become policy violations.

Devin Review

@seonghobae seonghobae added priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: maintenance Maintenance, build, dependency, or operational upkeep labels Sep 2, 2026 — with ChatGPT Codex Connector

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

⚠️ 1 issue in files not directly in the diff

⚠️ Restricted licenses escape policy review

Seven LicenseRef-NVIDIA-Proprietary components are marked unflagged. Unknown and non-standard licenses also disappear from the commercial-permissive policy review.

Devin Review

…#1960)

`opencode-review-dispatch.yml`'s `emit_strix_provider_failure_finding`
rendered one fixed finding for every `STRIX_PROVIDER_UNAVAILABLE` line, whose
Root cause read "The contextual-orchestrator gateway or its discovered
provider pool was unavailable for this run".

#1953 had just given the Strix sandbox bootstrap failure its own second
verdict token, `STRIX_SANDBOX_UNAVAILABLE`, precisely because that attribution
is wrong for it: the sandbox container never reaches its Caido proxy, so the
run dies before the gateway serves anything. This consumer re-applied the
wrong attribution one step downstream, into the review findings and the
failure census -- the misattribution #1953 fixed in the gate, surviving in the
reader.

The emitter now branches on the second token. A sandbox verdict gets a finding
that names Strix's sandbox, states that the verdict does not name the gateway,
and tells the reader not to change gateway or provider configuration on its
strength. A `STRIX_PROVIDER_UNAVAILABLE` line without the token keeps its
existing four lines verbatim, so the gateway class has no regression surface.

No test covered this finding text at all before ("gateway or its discovered
provider pool" and "provider availability blocked" both matched nothing under
tests/). tests/test_opencode_dispatch_strix_sandbox_finding.py runs the
production emitter, extracted from the published run block with the existing
_extract_run_block harness, and pins three directions: the sandbox token, a
gateway failure without it, and evidence carrying no provider-unavailable
signal at all.

Editing the workflow moves its blob, so REVIEW_DISPATCH_BLOB_SHA in
tests/test_pr_review_autofix_nvidia_nim_contract.py is recomputed to
694c04b with git hash-object (lane peer 1
flagged this pin in advance).

Gate on this tree: 2931 passed, 1 skipped, 21 subtests; coverage 100% (0
missed); interrogate 100%. Negative control on origin/main's workflow with
this test file: 1 failed, 2 passed -- only the sandbox direction fails there.

Refs #1953, #1935.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
cwl-sbom-inventory[bot] and others added 20 commits September 6, 2026 14:41
)

The contract asserted that expressions appear in the concurrency block, which
the block's own documentation satisfies while the key says something else. Slice
to the group's value with comments stripped so the assertion tests the key.

Author: separate session. Verified independently: mutant controls 7/7 caught on
the branch, 7/7 missed on main, adversarial helper inputs leak no comments.

Merger verification (this session): head matched the verified SHA exactly, 0
behind main, merge tree identical to the branch tree, tests-only (2 files, no
path outside tests/). Own discriminating control -- collapse the group key to
the repository alone while moving the expressions into the comment beside it:
main 58 passed (misses it), branch 1 failed (catches it). Full gate on the merge
tree: 2958 passed, 1 skipped, coverage 100%, interrogate 100%.

Merged under the standing chicken-and-egg authorization: the required contexts
CodeQL compatibility analysis (actions)/(python) cannot be produced for a
code-touching pull request in this repository -- codeql-scan-dispatch.yml has
never succeeded (0 of 1931) because its actor allowlist admits no identity that
dispatches it. See #1929.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#1964)

Move the concurrency group from job level to workflow level in both agent-mention
dispatch workflows so a superseded mention is coalesced while it is still queued,
instead of holding its queue slot until a runner frees up.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ck (#1975)

The helper sliced from `permissions:`, so it raised IndexError on the two
workflows that declare permissions first, and it returned a folded key's raw
newlines rather than the value YAML produces. Nine of twenty-nine
workflow-level keys are folded, including every required review workflow.

Author and verifier were separate sessions. Merger verification (this session,
independent runs): head matched GitHub exactly, 0 behind main, merge tree
identical to the branch tree, tests-only. Exact-match against a yaml oracle
across every workflow: 29 match, 0 mismatch, 0 exception. Seven adversarial
inputs pass, three of them designed here rather than reused -- a comment
quoting `group:` before the real key, a job-level concurrency block appearing
first in the file, and literal `|`/`|-` scalars, which are refused rather
than silently folded into a value YAML never produces. Two-way control on the
live hole: flipping noema-review.yml's cancel-in-progress to false behind a
comment passes on main (2961) and fails here. pr-review-autofix.yml's
deliberate cancel-in-progress: false is preserved. Gate: 2964 passed, 1
skipped, coverage 100%, interrogate 100%.

Bypass basis stated plainly: this change is tests-only and does not itself
unblock anything, so it does not meet the narrower 'the PR's own diff edits
review-pipeline files' reading recorded in
docs/product-technical-gap-baseline.md. It is merged under this session's
standing instruction to fix the queue, which names verifying
`cancel-in-progress: true` as part of that work. The required CodeQL contexts
remain unreachable for any code-touching PR here (#1929).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ot materialize (#1973)

Materializing the PR merge tree is a precondition of coverage-source-tree, so a
conflicting head can only produce a failed dispatch. The guard returns before
review_dispatch_admitted, preserving the bounded admission budget for a PR a
review could actually finish. UNKNOWN is deliberately not blocked.

Authored, verified and merged by three separate sessions.

Merger verification, my own runs: head matched GitHub, 0 behind main, merge tree
identical to the branch tree. Against current main the diff is 2 files, 206
insertions, 0 deletions; the production change is 29 added lines and nothing
removed. The guard sits at line 3691 and review_dispatch_admitted at 3706, so
the budget is preserved; 6 call sites handle the new return value. Negative
control, removing only the 15 guard lines: exactly 2 tests fail --
test_review_dispatch_skips_a_head_whose_merge_tree_cannot_materialize and
test_review_dispatch_reads_the_rest_merge_state_not_only_graphql -- asserting
merge_conflict against a received dispatched. Gate: 2968 passed, 1 skipped,
coverage 100% (13196 statements, 0 missed), interrogate 100%.

The cited measurement was corrected before merge. It read '20 dispatches across
80.5 hours'; two sessions independently recounted .github#1529 as 27 dispatches
across 100.8 hours with zero successes (20 cancelled, 7 failed). The original
figure came from a run window that silently truncated before the pull request
existed. The comment now carries the corrected numbers and the window.

Authorization is this session's standing instruction to clear the queue, which
lives outside this repository's text -- as docs/product-technical-gap-baseline.md
itself records after a 2026-09-01 correction, and that file is annotated '(not
merge authorization)' at every entry point. Corroborating rather than
authorizing: this PR's own diff edits scripts/ci/ review-pipeline code, so it
cannot validate itself across the pull_request_target trust boundary, which is
the conservative condition that document records one earlier pass imposing on
itself. On this head all 12 required contexts are unsatisfiable: 9 never
reported, 3 queued, 0 passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fails (#1979)

strix.yml's workflow-level cancel-in-progress was guarded by nothing: its own
test asserted the string as a substring, and the list in
test_required_pull_request_workflows_cancel_superseded_runs did not include it.

Authored and verified by separate sessions. Merger verification, my own runs:
head agreed across three paths (local ref, ls-remote, PR head) after the author
hit a push/PR-creation mismatch on this branch; 0 behind main; merge tree
identical to the branch tree; 13 files, all under tests/. Assertion forms: 24
helper calls, 4 line-anchored regexes, 19 assertions replaced.

Two-way control, comment out strix.yml's flag and set it false: main reports
2968 passed and does not catch it; this branch fails 2 tests. Gate on the branch
tree: 2968 passed, 1 skipped, coverage 100% (13196 statements, 0 missed),
interrogate 100%.

Four workflows are deliberately left uncontracted because no test states their
intended value, and writing one would invent policy. One of them,
scheduled-security-scan.yml, does produce the required context 'Detect CodeQL
languages' -- which strengthens rather than weakens that choice: its
cancel-in-progress: true with a github.ref-shared group is what starved it to
228 cancellations and 0 completions over 2026-09-01..09-05, so the correct value
is an open policy question on #1800, not a contract to fix here.

Authorization is this session's standing instruction to clear the queue, which
lives outside this repository's text. Corroborating, not authorizing: on this
head none of the 12 required contexts can pass -- the CodeQL pair is
unreachable while codeql-scan-dispatch has never succeeded (#1929).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…an workflows (#1980)

python-security.yml and sast-semgrep.yml had only the presence of
cancel-in-progress asserted, so flipping it to false passed the whole suite.
This pins the value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…review runs (#1983)

`active_review_run_refs` matched a workflow run's `name` exactly against the
review workflow aliases. But eight workflows in this repository define
`run-name:`, and that set contains every workflow whose runs this matcher looks
for -- `opencode-review.yml` ("Required OpenCode Review"),
`opencode-review-dispatch.yml` ("OpenCode Review Dispatch") and `strix.yml`
("Strix Security Scan"). For such a workflow GitHub reports the *rendered* run
name in `name` -- the same string as `display_title`, e.g.

    OpenCode Review Dispatch #834e748ee6...

Sampled 2026-09-07: 100 of 100 opencode-review-dispatch runs carry that form
and none carries the bare workflow name. So the exact match dropped every
production dispatch run at this line, before the `event == "repository_dispatch"`
branch immediately below that exists to read them. Two consequences:

  * `already_running` never suppressed a same-head repeat. .github#1529 took 27
    dispatches on one unchanged head over 100.8 hours; each new run's creation
    preceded the previous run's cancellation by about three seconds, so the
    previous run was demonstrably still active when the check ran and did not
    see it.
  * `stale` never populated, so older-head central runs were never cancelled.

A first count of the live queue said "20 duplicates of 45 active runs" and was
wrong: it grouped by repository and PR without the workflow, so runs of
different dispatch workflows on one PR were counted as duplicates of each other.
Regrouped by (workflow, repository, PR):

    active repository_dispatch runs, queued + in_progress   33
      codeql-scan-dispatch.yml      25 runs / 12 keys / 13 same-head duplicates
      opencode-review-dispatch.yml   5 runs /  5 keys /  0 duplicates
      pr-review-autofix.yml          3 runs /  3 keys /  0 duplicates

So the workflows this matcher governs show no live duplication at this instant.
The harm this fix addresses is the historical chain on .github#1529 and a
suppression that has never once fired, not a backlog visible right now. The 13
duplicates all belong to CodeQL Scan Dispatch, which this matcher does not
govern; that workflow also defines `run-name:`, which makes it a separate lead
rather than evidence for this change. Reviving stale cancellation is separately
safe: of 163 non-terminal central runs, 49 are review or dispatch
kind and 4 become cancellable, all of them subjects that no longer exist (3
closed or merged PRs, 1 moved head).

The fix is confined to the run comparison. `OPENCODE_WORKFLOW_NAMES` is
unchanged, because its other consumer compares a *workflow* object's name,
which is genuinely bare. `active_review_run_refs` has exactly two call sites,
OpenCode's and Strix's, so both are fixed here; the Strix side is pinned by its
own test so a later narrowing to the OpenCode aliases cannot silently reopen
half of it.

This is one instance of a class, and the file already contains the stable form.
`run.name` is compared as an identifier at four places -- `:1250`, `:3198`,
`:3254` (this one) and `:3783` -- while `:3060` keys on
`run.get("workflow_id") or run.get("path") or run.get("name")`, which cannot be
rewritten by a `run-name:`. `:1250` in particular feeds the REST fallback's
workflow-level policy boundary and would see a rendered title where it expects a
workflow name. Fixing the whole class means moving the callers from display
names to paths, which also touches how `dispatch_title_prefixes` is built, so it
is deliberately left out of this change; .github#1941 is the same root seen from
the `display_title` side. Recorded here so the next reader does not rediscover
it as a fifth instance.

Note the new behaviour this enables: while a same-head central run is active,
a repeat is now suppressed. A run that never terminates would therefore hold
the PR, where before the check simply never fired.

The existing fixture sets a bare `name` beside a rendered `display_title`, a
payload GitHub never emits for a `run-name:` workflow, which is why 100 percent
line coverage of that branch never revealed that production could not reach it.

Developer experience: the scheduler's same-head suppression and stale-run
cancellation work against real payloads instead of a shape only the tests
produce.
User experience: a pull request stops accumulating duplicate concurrent review
runs that cancel each other, so a review that starts can finish.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ree cannot materialize (#1973)" (#1985)

This reverts commit ad0779b.

I wrote that guard and its justification is false. It blocked every OpenCode
dispatch on a DIRTY/CONFLICTING head on the grounds that "a conflicting head can
only produce a failed dispatch". The run object does conclude failure, but the
review is published anyway: the reviewer reads the pull request diff, not a
merge tree -- "Coverage is a separate gate", in the review's own words -- and
only `coverage-source-tree` needs the merge commit.

Measured on .github#1529, the PR that motivated the guard: the last of its 27
dispatches published a 2404-character review at 2026-09-05T19:40:58Z. That
review body carries its own run id, 33969161561, which concluded failure at the
receipt gate nine seconds later. It is the only OpenCode review that head has
(4 reviews total, 1 by opencode-agent[bot]) and it is why the PR now reads as
reviewed. The guard would have discarded it. The pattern is not unique to
#1529: .github#1555 is CONFLICTING right now and its current head carries a
2019-character CHANGES_REQUESTED review from the same reviewer.

I reached "produced nothing" by reading run conclusions, which are roll-ups
that cannot name what a run did.

The cost the guard claimed to protect is also wrong by two orders of magnitude.
Across all 27 dispatches of that head, 109 jobs: 27 were allocated a runner for
0.24 h in total, 82 never were, and the rest of the elapsed time was queue
residency. Blocking the whole chain would have saved fourteen minutes of runner
time.

The repeat itself is a real problem, and it is fixed at its cause rather than
here. `active_review_run_refs` matched a run's `name` exactly against the
review workflow aliases, but the central review workflows define `run-name:`,
so GitHub sends the rendered title in that field and every dispatch run was
filtered out before the check could see it -- `already_running` never fired.
With that repaired, a conflicting head receives one dispatch and the next is
suppressed while it runs, which is the outcome this guard was reaching for
without discarding the review.

Developer experience: the scheduler no longer prints a skip reason that asserts
an outcome contradicted by the runs it cites.
User experience: a conflicting pull request receives a review and repair
guidance, instead of repair guidance alone.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…etector (#1987)

Two unrelated audits share one job in audit-central-ruleset.yml, and the
ruleset step runs first. It has exited 1 since at least 2026-09-04 on
owner-configured governance drift:

    ERROR: exactly two approving reviews are not required
    ERROR: last-push approval protection is disabled
    FAIL: ruleset 18156473 has 2 governance drift reason(s)

Live values on ruleset 18156473 today are `required_approving_review_count: 1`
and `require_last_push_approval: false`, against the 2 and true the audit
asserts. Both are owner-configured settings, and this change does not touch
either them or the audit's expectations: with every session sharing one GitHub
identity and unable to approve another's pull request, a two-approval
requirement may well have been relaxed deliberately, in which case the stale
side is the assertion rather than the configuration. Deciding that is an owner
call.

What is not an owner call is the collateral damage. Because the failure exits a
shared job, the two steps below it never ran: the CodeQL coverage detector and
the backlog-38 bootstrap that opens CodeQL setup pull requests. So the detector
that would have reported a coverage gap has been dead for days, and its
workflow was red the whole time for an unrelated reason -- red status, wrong
subject, and no signal about coverage either way.

The coverage step now carries `if: always()`. It builds its own repository list
into its own temp file and the step above exports nothing to GITHUB_ENV or
GITHUB_OUTPUT, so it has no data dependency to lose; the job still fails
overall. The bootstrap step deliberately does not get the same guard, because
it opens pull requests and running a mutation after an unexplained upstream
failure is a different decision from running a read-only detector. A contract
test pins both halves.

The detector also needed a correction of its own. It accepted
`default_setup_state == "configured"` as coverage, but a repository can report
`configured` with an **empty** `languages` list, which scans nothing. Measured
2026-09-07: life-os, aFIPC and inkspan all report that shape, and life-os has
zero CodeQL analyses of any language while codeql-pr.yml still runs on every
pull request head. The control holds in both directions -- html4tree, naruon
and wardnet have non-empty language lists and do have `dynamic/` analyses for
exactly those languages. The audit workflow now collects `languages` alongside
`state`, the predicate requires a non-empty list, and a payload missing the new
key fails closed rather than falling back to the state alone.

Gaps of the two kinds are reported as different sentences, because they need
different fixes: enable languages on an existing setup, versus set coverage up
at all.

A reviewer then asked whether the newly-unblocked step could run and audit zero
repositories while still passing, and one layer below the fix it could:

    $ echo '[]' | python3 scripts/ci/audit_org_codeql_coverage.py
    PASS: all 0 repositories have real CodeQL coverage        exit 0

The calling workflow already refuses that -- its sentinel check requires known
private repositories to appear in the enumeration, which an empty list fails --
but the script is directly runnable against a JSON path or stdin, so the guard
did not cover every entry point. `main` now refuses an empty payload. This is
the same vacuous-pass shape as the `configured`-with-no-languages case above,
one level down, which is where it was found: a pass that examines nothing is
not a pass.

The step's independence from the failing step above it is established
mechanically rather than by reading the YAML. Steps can only share state
through `GITHUB_ENV`, `GITHUB_OUTPUT`, `GITHUB_PATH` or files, since each `run:`
is a separate shell. The ruleset step uses none of those channels, and the two
steps' `$RUNNER_TEMP` paths are disjoint: `central-required-workflow-*`,
`ruleset-probe-*` and `stacked-opencode-ruleset.*` against `codeql-coverage-*`,
`codeql-analysis-*` and `codeql-default-setup-*`.

Developer experience: a governance-drift failure no longer hides an unrelated
security-coverage result, and the audit says which of the two problems a
repository has.
User experience: a repository whose CodeQL setup is switched on but scanning
nothing is reported as uncovered instead of counted as covered.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…1989)

#1987 taught the CodeQL coverage audit to refuse an empty payload, because
"PASS: all 0 repositories have real CodeQL coverage" reads as success over a
run that examined nothing. Reviewing that change, host 2 fed it a payload of a
single *archived* repository:

    PASS: all 1 repositories have real CodeQL coverage        exit 0

Non-empty, so it clears the new guard, and archived repositories are then
legitimately skipped by the coverage loop. The subject set is empty again, by a
different route -- the same defect the guard was added to close, one input shape
sideways from the one it checks.

The count that matters is what the audit examined. `auditable_repositories()`
is now the single place that decides which repositories are in scope, shared by
the loop and by the guard, so the two cannot drift apart when the archived rule
changes. The guard refuses an empty examined set however it became empty, and
the PASS line reports the examined count rather than the supplied one, so an
organization of nothing but archived repositories can no longer be reported as
fully covered.

Developer experience: the pass line's number is the number of repositories the
run actually checked.
User experience: an audit that examined nothing says so instead of passing.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
cwl-sbom-inventory[bot] and others added 6 commits September 7, 2026 05:49
Per-language codeql-scan-dispatch runs were occupying the 60-job
ceiling: 149 queued handler runs across 60 PR@SHA tuples, and
duplicate cancel could not collapse them because the language is
absent from the run name, job name, and REST payload.

analyze-head shards still publish the required check name and still
fail pending to release the runner, but they no longer POST.
dispatch-current-head collects this run's language job ids and sends
one codeql-scan payload (matrix + required_jobs). The handler
concurrency group is {workflow}-{repository}-{PR}; language
independence is fail-fast: false on that run's job matrix.

ADR-0025's 2026-09-05 rejection of a full-matrix dispatch is
superseded. The sibling-cancel failure from
contextual-orchestrator#1049 / run 33938784437 is gone because
siblings are jobs in one run.
#2008 made required_jobs mandatory on the default-branch handler.
repository_dispatch runs that file, so payloads that lined up before
the merge still carry required_language + required_job_id and a
one-shard matrix. Validate now synthesizes required_jobs from those
scalars when the array is empty, the matrix length is 1, and the
language matches. A present required_jobs array still wins; missing
or mismatched identity still fails closed. Concurrency stays
{workflow}-{repository}-{PR} with no language suffix.

Developer experience: queued single-language dispatches validate
instead of all failing closed after the cutover.
User experience: required CodeQL compatibility checks for those
in-flight PRs can still complete.

@cwl-noema-review cwl-noema-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noema LLM review

The PR refreshes several workflow concurrency groups, adds a coordinator job for CodeQL dispatch, improves allowlist parsing to support multiple trusted actors, and enhances audit coverage reporting. The changes are consistent with the stated rationales, preserve the existing authorization invariants, and introduce no confirmed concrete regressions.

Reviewed changed lines

  • .github/workflows/agent-mention-noema-dispatch.yml:17 (RIGHT): Moves concurrency from the job level to workflow level. The workflow has a single job and the job-level block is removed, so there is no same-group self-wait risk and queued runs coalesce earlier.
  • .github/workflows/agent-mention-opencode-dispatch.yml:17 (RIGHT): Moves concurrency from the job level to workflow level. The workflow has a single job and the job-level block is removed, so there is no same-group self-wait risk and queued runs coalesce earlier.
  • .github/workflows/codeql-scan-dispatch.yml:157 (RIGHT): Parses ALLOWED_DISPATCH_ACTOR as a comma-separated allowlist while requiring non-empty actors; an empty allowlist continues to admit nothing.
  • .github/workflows/codeql-scan-dispatch.yml:524 (RIGHT): The wake job condition reads validated output required_jobs and only proceeds when non-empty, avoiding a wake with missing job bindings.
  • .github/workflows/opencode-review-dispatch.yml:150 (RIGHT): Uses the same comma-separated allowlist parsing with a non-empty guard, permitting multiple trusted dispatch identities without weakening empty-list denial.

Adversarial validation

  • .github/workflows/agent-mention-noema-dispatch.yml:17 (RIGHT) falsified: Moving concurrency to workflow level could cause a run to wait on its own group when job-level and workflow-level groups match. — The diff removes the job-level concurrency block entirely, leaving only the workflow-level group, so no job requests the group its own run already holds.
  • .github/workflows/agent-mention-opencode-dispatch.yml:17 (RIGHT) falsified: Moving concurrency to workflow level could cause a run to wait on its own group when job-level and workflow-level groups match. — The diff removes the job-level concurrency block entirely, leaving only the workflow-level group, so no job requests the group its own run already holds.
  • .github/workflows/codeql-scan-dispatch.yml:157 (RIGHT) falsified: Parsing ALLOWED_DISPATCH_ACTOR with IFS=',' could produce an empty actor that is admitted. — The loop checks allowed_actor is non-empty before comparing against DISPATCH_ACTOR and DISPATCH_SENDER, so an empty allowlist admits nothing.
  • .github/workflows/codeql-scan-dispatch.yml:524 (RIGHT) falsified: Using validated output required_jobs in the wake condition could let a wake job run when no valid job ids were bound. — The wake job condition explicitly requires needs.validate-dispatch.outputs.required_jobs != '', preventing an empty jobs list from triggering the job.
  • .github/workflows/opencode-review-dispatch.yml:150 (RIGHT) falsified: Parsing ALLOWED_DISPATCH_ACTOR with IFS=',' could produce an empty actor that is admitted. — The loop checks allowed_actor is non-empty before comparing against DISPATCH_ACTOR and DISPATCH_SENDER, so an empty allowlist admits nothing.
  • Residual risk: Low. The audited probes attempted concrete regressions around deadlocks, empty allowlists, and malformed job wake inputs and were all falsified against the changed lines.

Findings

  • No blocking findings.
  • Result: APPROVE
  • Head SHA: 5f264b19eea2559b4d8ce765e158d7d414bf90eb
  • Reviewer credential: noema-review-github-app-refresh
  • Actor: cwl-noema-review[bot]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: maintenance Maintenance, build, dependency, or operational upkeep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant