Skip to content

fix(operations): audit orphaned Actions workflow identities - #32

Open
seonghobae wants to merge 15 commits into
mainfrom
fix/actions-registry-audit
Open

fix(operations): audit orphaned Actions workflow identities#32
seonghobae wants to merge 15 commits into
mainfrom
fix/actions-registry-audit

Conversation

@seonghobae

@seonghobaeseonghobae commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Buyer and control-plane incident

Issue #31 proves that protected main contains four supported workflow sources while the live GitHub Actions registry reports 27 identities, including historical PR #20 repair, bootstrap, diagnosis, and finalizer paths that remain state: active after their YAML was deleted. Source deletion is therefore not complete workflow lifecycle cleanup.

This PR adds a read-only, exact-revision lifecycle audit. It does not restore historical repair workflows, disable workflow records, add an Actions-write credential, change release blocker #17, or weaken PR #20's post-release integration gate.

GREEN: complete implementation

Exact contributor head: c005f29f3b56625ba039c2ea94e69d80ab512989
Exact protected-main parent: e10bbd8939a249f67ffec7253dfcee667178e7fb

scripts/ci/actions_registry_audit.py now implements the complete committed design:

  • exact repository/SHA/workflow-path identity validation (normalize_repository, normalize_sha, normalize_workflow_path, including NFC/traversal/duplicate-separator rejection);
  • complete, verified pagination for the workflow registry and open same-repository pull requests, with total-count agreement, repeated-page rejection, and a hard page cap;
  • exact protected-main and PR-head Git tree reads, failing closed on a truncated tree;
  • the seven-way finite classification model (present_active, present_disabled, active_pr_workflow, orphan_active, orphan_disabled, dynamic_owned, unresolved);
  • a start/end protected-main SHA revalidation so a branch move mid-audit is detected rather than silently bound to stale evidence;
  • deterministic, schema-versioned (threadweave.actions-registry-audit/v1) JSON evidence with an atomic writer;
  • a strict GitHubJsonClient: bounded response size, duplicate-JSON-key rejection, https-only scheme enforcement, and token-redacted diagnostics.

.github/workflows/actions-registry-audit.yml runs the detector with exactly actions: read, contents: read, and pull-requests: read — no mutation authority — on protected-main changes to the detector, on manual dispatch, and hourly at minute 53. It deliberately does not run on pull_request: the audit is meant to fail visibly on a genuine live orphan, and while any real orphan remains undisabled (which is currently true — see below) that would make it a permanently red check on every unrelated PR. tests/test_actions_registry_audit.py already provides exact PR-time contract coverage of the detector itself through ci.yml.

ADR-0010 records the observation/disable-authority separation and is wired into docs/adr/README.md, docs/TRACEABILITY.md, docs/INCIDENT_RUNBOOK.md, docs/THREAT_MODEL.md, docs/TEST_STRATEGY.md, and docs/operations/hourly-autonomous-maintenance.md.

Verification

Numbering note

The original design doc reserved "ADR-0009" for this decision; ThreadWeave#34 claimed ADR-0009 for the LineageWeave/naruon consumer boundary first (merged independently, unrelated topic). This PR's decision is recorded as ADR-0010 instead, with the design/plan docs' cross-references updated to match.

Authority and dependency boundary

Protected-main integration is still intermediate: issue #31 closes only after an authorized operator independently revalidates the exact live ledger, disables only confirmed active orphan IDs through the GitHub Actions lifecycle API, preserves ci, Hourly PR Maintenance, Hourly Product Development, Release ThreadWeave, and Actions Registry Audit, and records before/after evidence. This PR only produces the evidence; it does not perform that disablement.

Related: ThreadWeave #31, ContextualWisdomLab/.github#945, ContextualWisdomLab/appguardrail#929.

Summary by CodeRabbit

  • 새 기능

    • GitHub Actions 레지스트리를 매시간 또는 수동으로 점검하는 읽기 전용 감사 기능을 추가했습니다.
    • 워크플로 상태를 7개 범주로 분류하고, 고립된 활성 워크플로 ID에 대한 비활성화 권고를 JSON 보고서로 제공합니다.
    • 감사 결과를 실행 성공 여부와 관계없이 최대 90일간 보관합니다.
    • 실제 워크플로 비활성화 없이 최소 읽기 권한으로 안전하게 실행됩니다.
  • 문서

    • 사고 대응 절차, 운영 가이드, 위협 모델 및 변경 기록을 업데이트했습니다.
  • 품질 개선

    • 브랜치·워크플로·PR 상태 변경과 비정상 응답을 감지해 안전하게 실패하도록 검증을 강화했습니다.

@coderabbitai

coderabbitaiBot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in:41 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4958545a-1902-4dfa-8083-42cadb14ce0d

📥 Commits

Reviewing files that changed from the base of the PR and between 78ac1a6 and 91a0535.

📒 Files selected for processing (2)
  • scripts/ci/actions_registry_audit.py
  • tests/test_actions_registry_audit.py
📝 Walkthrough

Walkthrough

읽기 전용 Actions 레지스트리 감사기, 예약 워크플로, 결정적 JSON 보고서, fail-closed 테스트 및 운영 문서를 추가했습니다. 감사기는 보호된 main과 동일 저장소 PR head를 기준으로 workflow identity를 분류합니다.

Changes

Actions 레지스트리 감사

Layer / File(s)Summary
감사 계약과 분류
scripts/ci/actions_registry_audit.py, tests/test_actions_registry_audit.py, docs/superpowers/specs/..., docs/superpowers/plans/...
저장소, SHA, workflow 경로와 API 응답을 엄격히 검증합니다. 레지스트리 항목을 7개 분류로 나눕니다.
스냅샷 수집과 보고서 생성
scripts/ci/actions_registry_audit.py, tests/test_actions_registry_audit.py
레지스트리, 동일 저장소 PR head, Git tree를 수집합니다. main SHA, workflow inventory, PR snapshot drift와 잘린 응답을 거부합니다. 결정적 JSON 보고서를 원자적으로 기록합니다.
HTTP 클라이언트와 CLI
scripts/ci/actions_registry_audit.py, tests/test_actions_registry_audit.py
HTTPS, 토큰, 응답 크기, UTF-8, 중복 JSON 키와 쿼리 인코딩을 검증합니다. CLI는 감사 결과와 오류에 따라 종료 코드를 반환합니다.
워크플로와 품질 게이트
.github/workflows/actions-registry-audit.yml, .github/workflows/ci.yml, tests/test_actions_registry_audit_workflow.py, tests/test_autonomous_documentation.py, tests/test_workflows.py, .gitignore
시간별·수동 감사 워크플로를 추가합니다. actions: read, contents: read, pull-requests: read 권한만 사용합니다. 커버리지와 계약 검사를 CI에 연결합니다.
운영 및 거버넌스 문서
docs/adr/*, docs/operations/*, docs/INCIDENT_RUNBOOK.md, docs/TEST_STRATEGY.md, docs/THREAT_MODEL.md, docs/TRACEABILITY.md, CHANGELOG.md
감사 결과 확인과 실제 workflow 비활성화 권한을 분리하는 운영 절차와 ADR-0010을 기록합니다.

Estimated code review effort: 5 (Critical) | ~90+ minutes

Merge Risk:🔵 Low · up to 78ac1

The PR adds a read-only hourly audit, but malformed workflow records may not be included in drift detection and high pull-request volumes could increase API rate-limit pressure without telemetry. The change is mergeable with explicit owner awareness and follow-up on these bounded risks.

Sequence Diagram(s)

sequenceDiagram
participant Scheduler_or_Operator
participant Actions_Registry_Audit_Workflow
participant actions_registry_audit_py
participant GitHub_API
participant Evidence_Artifact
Scheduler_or_Operator->>Actions_Registry_Audit_Workflow: 예약 또는 수동 실행
Actions_Registry_Audit_Workflow->>actions_registry_audit_py: audit --repository --output 실행
actions_registry_audit_py->>GitHub_API: registry, PR, tree 조회
GitHub_API-->>actions_registry_audit_py: 검증된 API 응답
actions_registry_audit_py-->>Actions_Registry_Audit_Workflow: 보고서 및 종료 코드 반환
Actions_Registry_Audit_Workflow->>Evidence_Artifact: 감사 보고서 업로드
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 26.74% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 172 functions across 5 files.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ Passed제목은 고아 GitHub Actions 워크플로 ID를 감사하는 이번 변경의 핵심 목적을 정확하고 간결하게 설명합니다.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/actions-registry-audit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

seonghobae added a commit that referenced this pull request Aug 22, 2026
The Actions-registry-audit design doc lives at
docs/superpowers/specs/2026-08-12-actions-registry-audit-design.md on PR
#32's branch, not docs/plans/. That design doc also reserves "ADR-0009" for
its own future decision record, which now collides with the ADR-0009 this
PR adds for the LineageWeave consumer boundary. Note both facts in the gap
baseline so PR #32's eventual GREEN implementation uses ADR-0010 instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
seonghobaeand others added 3 commits August 22, 2026 18:47
Replace the RED-only stub with the full read-only auditor: exact
repository/SHA/workflow-path identity validation, complete verified
pagination for workflows and open same-repository pull requests, exact
protected-main and PR-head Git tree reads, the seven-way finite
classification model, deterministic schema-v1 evidence, an atomic report
writer, and a strict GitHubJsonClient (bounded response size, duplicate
-key rejection, redacted diagnostics). Add
.github/workflows/actions-registry-audit.yml with exactly actions:read,
contents:read, and pull-requests:read -- no mutation authority.
Add ADR-0010 (renumbered from the design doc's original ADR-0009, which
ThreadWeave#34 claims first for the LineageWeave/naruon consumer
boundary) recording the observation/disable-authority separation, and
wire it into docs/adr/README.md, docs/TRACEABILITY.md, and
docs/INCIDENT_RUNBOOK.md's orphaned-workflow recovery path.
102 tests, exact 100% statement/branch coverage on the new module
(matching the existing scripts/ci focused-coverage CI gate), 100%
docstring coverage via tests/test_autonomous_documentation.py.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…aybook
Record the Actions registry audit's third hourly heartbeat (minute 53,
least-authority actions:read/contents:read/pull-requests:read), its
fail-closed hostile-input test requirements, and the CHANGELOG entry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
github-advanced-security[bot]

This comment was marked as resolved.

seonghobae added a commit that referenced this pull request Aug 22, 2026
Update the gap baseline: PR #32's Actions registry auditor is now fully
implemented (identity/path validation, verified pagination, tree reads,
seven-way classification, atomic evidence, least-authority workflow;
102 tests, 100% statement/branch/docstring coverage) and recorded as
ADR-0010, resolving the earlier numbering collision note.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
github-code-quality[bot]

This comment was marked as resolved.

@opencode-agentopencode-agentBot added area: ci-cd CI, GitHub Actions, checks, release, or supply chain priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026
- actions-registry-audit.yml pinned `ref: main` even on `pull_request`
events, so the PR's own new script was never checked out and the run
failed with "No such file or directory". Drop the override; checkout's
default ref already resolves correctly per trigger (PR merge ref on
pull_request, default branch tip on push/schedule/workflow_dispatch).
- Semgrep flagged python.lang.security.audit.dynamic-urllib-use-detected
on the GitHubJsonClient's urlopen call. Add an explicit https-only
scheme guard (closing the file:// read vector the rule warns about)
and suppress with the same nosemgrep/nosec pattern already established
in ContextualWisdomLab/.github's materialize_base_python_requirements.py
for this exact rule, justified inline: base_url defaults to the literal
"https://api.github.com" and is never overridden in production, only
the already-validated path/query varies.
Verified locally against real Semgrep (0 findings) and by actually
running the audit against ContextualWisdomLab/ThreadWeave's live
registry: it reproduces issue #31's finding exactly (21 confirmed
orphan_active records, all named PR #20 repair/bootstrap/finalizer
workflows; 4 present_active; 1 active_pr_workflow for this PR's own new
workflow). 103 tests, 100% coverage.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Running the live audit on every PR made the check permanently red: the
tool correctly found 21 real confirmed orphan_active workflows in
ThreadWeave's actual live registry (verified locally, matching issue
#31's incident exactly), and the workflow is designed to fail visibly
whenever it finds one. That is the right behavior for an incident
signal on its own schedule, but it would block every unrelated PR from
merging until an authorized operator disables those orphans separately
-- a scope this detector deliberately does not have.
Keep push-to-main-on-detector-change, workflow_dispatch, and the
hourly heartbeat. PR-time contract verification for the detector's own
correctness already exists: tests/test_actions_registry_audit.py runs
at exact 100% coverage in ci.yml on every touching PR. Add
tests/test_actions_registry_audit_workflow.py locking the trigger,
permission, pin, and evidence-upload contract so this doesn't regress.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae marked this pull request as ready for review August 22, 2026 10:54
devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

…udit
Real correctness/security gaps CodeRabbit caught that I should have
caught myself:
- classify_workflow_records now detects duplicate normalized workflow
paths (two different workflow IDs silently sharing one canonical
source path) and marks both unresolved, mirroring the existing
duplicate-ID check.
- A path shaped like a repository workflow path
(`.github/workflows/...`) that fails strict normalization is now
`unresolved` rather than `dynamic_owned` -- that shape is
ambiguous/suspicious, not a legitimate GitHub-owned identity.
`dynamic_owned` is now reserved for paths that never claimed the
repository prefix at all.
- audit_actions_registry's final revalidation now matches the design
doc's own stated requirement (which I had only partially
implemented): it re-checks the live workflow ID set and the open-PR
number/head-SHA snapshot for drift, not only the protected-main
branch SHA.
- Added the report's UTC observation timestamp (also specified in the
design doc's report contract but missing from the actual encoder).
- Used urllib.parse.urlencode for query construction instead of naive
string joining.
Also fixed the design/plan docs' remaining stale references (ADR
filename still said 0009, workflow description still claimed a
pull_request trigger), corrected ADR-0010's TRACEABILITY.md maturity
label from implemented-main to active-PR (it isn't on protected main
yet), tightened INCIDENT_RUNBOOK.md's disable procedure to require a
fresh full audit run rather than a narrower per-ID check, and switched
one test's embedded NFD combining character to an explicit ́
escape for source clarity.
118 tests (was 106), exact 100% statement/branch coverage maintained.
Full suite 420/420. Semgrep/ruff/compileall clean. Re-verified against
ThreadWeave's live registry: still correctly reproduces issue #31 (21
orphan_active).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

seonghobaeand others added 2 commits August 22, 2026 22:07
CodeRabbit nitpick on #32: per-PR-head tree GETs scale linearly with
open PR count (bounded by MAX_PAGES * PULLS_PER_PAGE = 5,000 worst
case), with no request narrowing or 429 backoff. Real for a
pathologically large open-PR queue, not for ThreadWeave's actual
queue size today. Leave a ponytail comment naming the ceiling and the
upgrade path instead of building speculative backoff/filtering logic.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ring
Two more CodeRabbit findings on #32:
- main()'s docstring promises exit codes 0/1/2 only, but
write_report_atomically's OSError (permissions, missing parent
directory, disk full) propagated as an unhandled exception with an
unspecified exit code and no ::error:: annotation. Catch it and
return 2, matching the documented contract.
- classify_workflow_records' docstring said missing/malformed `path`
is unresolved, but the actual (intentional, fail-safe) behavior
routes a missing or non-string path to dynamic_owned alongside paths
that never claimed the repository prefix. Corrected the docstring to
describe the real behavior instead of changing the behavior to match
a stale docstring.
119 tests (was 118), exact 100% statement/branch coverage maintained.
Full suite 421/421. Ruff/Semgrep/compileall clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Devin (kind: bug) and github-code-quality found genuine defects on #32
that CodeRabbit's pass hadn't caught:
- classified.sort() used a bare (workflow_id is None, workflow_id) key.
Two unresolved records with differently-typed malformed raw ids (a
string vs a list, say) are not mutually comparable and would crash
the sort with TypeError instead of failing closed. Added
_classification_sort_key: valid positive ints sort numerically first,
everything else sorts by its always-comparable repr(). The repeated
-page fingerprint in list_workflow_records had the same class of bug
(an unhashable list id crashed the set membership check) -- fixed
the same way, caught by my own new sort-ordering test.
- The duplicate-path first pass counted a record's path toward
seen_paths regardless of whether that record's own id was valid,
so an already-unresolved garbage record sharing a path string with a
legitimate record could falsely drag the legitimate one into
unresolved too. Only count a path when its own record has a valid id.
- MAX_PAGES rejected a registry/queue whose true size lands exactly on
a page boundary (a multiple of per_page): confirming completion needs
one trailing empty-page request, which the old check misread as
exceeding the cap. Added _MAX_FETCHES = MAX_PAGES + 1 so that one
confirmation request is allowed without raising the true data ceiling
Applied to both list_workflow_records and list_open_pull_requests.
- The final revalidation compared only the workflow id *set*, so a
workflow whose state flipped (active to disabled) or path changed
mid-audit while keeping the same id passed undetected. Added
_workflow_identity_snapshot comparing (id, path, state) tuples instead.
- github-code-quality: _FINITE_CLASSIFICATIONS was defined but never
used -- now pre-seeds the report's summary at 0 for every
classification, so a consumer never has to guess whether an absent
key means zero or an unreported schema version. The _JsonGetter.get
protocol stub's bare `...` ("statement has no effect") is now an
explicit `raise NotImplementedError`. Two test stubs had a genuinely
unused `params = params or {}` reassignment -- removed.
125 tests (was 119), exact 100% statement/branch coverage maintained.
Full suite 427/427. Ruff/Semgrep/compileall clean. Re-verified against
the real live repository -- still correctly reproduces issue #31 (21
orphan_active), and the report summary now always shows all 7
classification keys.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Two more real findings (CodeRabbit + Devin, both on the same code, on
the latest push):
- _workflow_identity_snapshot excluded records with an invalid id from
its comparison set, so an already-unresolved (malformed-id) workflow
appearing or disappearing mid-audit never tripped the drift check --
even though that record's `unresolved` classification is still
evidence the final report asserts. Applied CodeRabbit's suggested
fix directly: repr() the id too instead of filtering on its
validity, so every record (valid or malformed id) is now part of the
comparable snapshot. Added a regression test.
- tests/test_actions_registry_audit.py imported the detector via
`from scripts.ci import actions_registry_audit`, which only resolves
when the repository root happens to already be on sys.path (true
under `python -m pytest` as CI/AGENTS.md invoke it, not guaranteed
for a bare `pytest` run from elsewhere). Every sibling script test in
this repository already loads by file path for exactly this reason
(tests/test_autonomous_documentation.py's `_load` helper) -- switched
to the same pattern. Verified a bare `pytest` run from a different
working directory now passes (it did not reliably before).
Devin's third finding on this round (PR-list pagination has weaker
loop guards than workflow pagination, since GitHub's /pulls endpoint
has no total_count) was explicitly marked "Acceptable, not a defect"
by the reviewer itself -- no change needed, acknowledged in the reply.
126 tests (was 125), exact 100% statement/branch coverage maintained.
Full suite 428/428. Ruff/Semgrep/compileall clean. Re-verified against
the real live repository.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…on text
A workflow record backed by an open-PR head but currently disabled was
classified active_pr_workflow with the same reason text used for an active
one, understating that it isn't actually running (Devin review finding on
PR #32). The classification bucket is unchanged -- a separate disabled/PR-head
bucket isn't warranted -- but the reason text now says so explicitly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

Open in Devin Review

Comment threadscripts/ci/actions_registry_audit.py
Comment threadscripts/ci/actions_registry_audit.py
Comment threadtests/test_autonomous_documentation.py
seonghobae added a commit that referenced this pull request Aug 23, 2026
…t cause
The PR/issue table had drifted from reality: PR #32's row still said
"Draft; CI in progress" (102 tests) when it's long since been marked
ready for review, been through several more review rounds, and reached
100% coverage with all threads resolved. PR #34 wasn't listed at all.
Issues #31/#22 didn't name the actual current blocker.
Added the concrete external root cause now confirmed for all of it:
ContextualWisdomLab/.github#624 (GitHub Models retirement + provider
credit exhaustion causing every OpenCode review-dispatch model-pool
candidate to fail org-wide) -- not a ThreadWeave-side or per-repo
scheduling delay. No repository-side action remains on #32, #34, #31,
or #22's criterion 5 until that clears.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@devin-ai-integrationdevin-ai-integrationBot added status: merge-ready and removed status: draft Draft pull request labels Aug 23, 2026

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CI passes and the audit detector matches issue #31. Approving for merge.

devin-ai-integrationBot added a commit that referenced this pull request Aug 23, 2026
- Make ADR-0009's Proposed status explicit and conditionalize conflict claims
- Align ADR-0009 dependency chain with product-technical-gap-baseline graph
- Fix baseline ADR-0010 citation to indicate it will be recorded after PR #32 merges
- Clarify PR #20 has both CONFLICTING state and issue #17 release-gate blockers
- Add architecture-test assertions that lock the branched dependency ordering
- Distinguish documentation PRs from production-integration PRs for LineageWeave references
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All checks green and remaining informational review threads are resolved.

seonghobae added a commit that referenced this pull request Aug 23, 2026
The PR inventory attributed #32 and #34 entirely to the #624 review-dispatch
outage. That sends the next contributor to the wrong repository: two further
root causes, both independently reproduced today, now sit between these PRs
and a merge.
- The org-wide `strix` failure is a provider-routing defect in `.github`'s
own `strix_quick_gate.sh`, not provider exhaustion. The gate recognized
only the underscored `openai_direct/` alias while `STRIX_FALLBACK_MODELS`
carries the hyphenated `openai-direct/` spelling that protected main's
trusted required-workflow smoke pins verbatim. Once NVIDIA NIM
rate-limited the first two models, the third fallback reached LiteLLM as
a literal unrecognized provider string. Reproduced three times; the same
signature fails LineageWeave's required `strix` check.
- `pull_request_target` resolves `job.workflow_sha` to the base branch, so
every `.github` PR's own `strix` check reads that script from protected
main regardless of the PR branch. A PR fixing that file cannot verify its
own fix, which is why the standalone attempt was closed as superseded.
Record both so the shared unblocker (`.github#1213` reaching main) is
explicit and nobody re-investigates from this repository.
@seonghobae
seonghobae enabled auto-merge (squash) August 24, 2026 00:50

@opencode-agentopencode-agentBot 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.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 91a05358df75b7324025896f8b79a22076202dcd.

  • Head SHA: 91a05358df75b7324025896f8b79a22076202dcd

  • Workflow run: 32699419292

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow (2 files)"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow (2 files)"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (2 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (2 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Docs (9 files)"]
S3 --> I3["operator or user guidance"]
I3 --> R3["Review risk: Docs (9 files)"]
R3 --> V3["docs review"]
Evidence --> S4["CI script: actions_registry_audit.py"]
S4 --> I4["review and security gate shell path"]
I4 --> R4["Review risk: CI script: actions_registry_audit.py"]
R4 --> V4["bash -n plus Strix self-test"]
Evidence --> S5["Test (4 files)"]
S5 --> I5["regression suite"]
I5 --> R5["Review risk: Test (4 files)"]
R5 --> V5["targeted test run"]
Loading

@opencode-agent

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 91a05358df75b7324025896f8b79a22076202dcd
  • Workflow run: 32699419292
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 91a05358df75b7324025896f8b79a22076202dcd.

  • Head SHA: 91a05358df75b7324025896f8b79a22076202dcd

  • Workflow run: 32699419292

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow (2 files)"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow (2 files)"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (2 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (2 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Docs (9 files)"]
S3 --> I3["operator or user guidance"]
I3 --> R3["Review risk: Docs (9 files)"]
R3 --> V3["docs review"]
Evidence --> S4["CI script: actions_registry_audit.py"]
S4 --> I4["review and security gate shell path"]
I4 --> R4["Review risk: CI script: actions_registry_audit.py"]
R4 --> V4["bash -n plus Strix self-test"]
Evidence --> S5["Test (4 files)"]
S5 --> I5["regression suite"]
I5 --> R5["Review risk: Test (4 files)"]
R5 --> V5["targeted test run"]
Loading

@opencode-agent
opencode-agentBot disabled auto-merge August 24, 2026 13:49
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-cdCI, GitHub Actions, checks, release, or supply chainpriority: mediumNormal-priority or P2 workstatus: merge-readytype: bugDefect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@seonghobae@github-advanced-security