Skip to content

feat(actions): inventory orphaned workflow identities - #1026

Open
seonghobae wants to merge 26 commits into
mainfrom
feat/orphaned-workflow-lifecycle-inventory
Open

feat(actions): inventory orphaned workflow identities#1026
seonghobae wants to merge 26 commits into
mainfrom
feat/orphaned-workflow-lifecycle-inventory

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Buyer-visible gap

GitHub persists Actions registry identities after the YAML leaves the protected default branch. Buyers and reviewers cannot treat "the file is gone" as "no writer remains enabled." That is a control-plane visibility gap (#945; ContextualWisdomLab/appguardrail#929; ContextualWisdomLab/clearfolio#423; ContextualWisdomLab/disksage#191).

What this PR adds

  • Read-only classifier scripts/ci/inventory_orphaned_workflows.py
  • Exact default-branch SHA binding (start == end, 40-hex)
  • Classes: present_active, present_disabled, orphan_active, orphan_disabled, dynamic_owned, unresolved
  • Fail-closed pagination, permission loss, 404/5xx (one retry), reused IDs, percent-encoded paths, branch movement
  • One-shot names are not heuristically invalid; missing source is classified from exact tree evidence
  • Refuses registry mutation; no COPILOT_GITHUB_TOKEN
  • APA 7 doctoring; CSAP/SOC 2 as design constraints, not certification claims
  • No operational PII mask

This is the executable contract increment. It does not disable workflows or claim a live org sweep is complete.

Verification

Local 2x coverage run -m pytest tests && coverage report --fail-under=100 and interrogate both passed at 100%.

Merge

Arm squash auto-merge. Do not self-approve. Two-approval + last-pusher 405 is a ruleset, not a coding stop.


Open in Devin Review

Summary by CodeRabbit

  • 새 기능

    • GitHub Actions 워크플로의 고아 상태를 읽기 전용으로 점검하고 분류하는 기능을 추가했습니다.
    • 기본 브랜치 기준으로 워크플로 상태를 검증하고, 확인된 항목을 소유자 이슈로 연결합니다.
    • 점검 결과를 정렬된 JSON 원장으로 출력할 수 있습니다.
  • 문서

    • 워크플로 수명 주기 점검 기준, 운영 절차, 롤백 방법을 문서화했습니다.
    • 수명 주기 원장 예시와 변경 내역을 추가했습니다.
  • 품질 개선

    • 불완전한 페이지네이션, 잘못된 입력 및 가시성 문제를 안전하게 감지합니다.
    • 자동 비활성화, 삭제 또는 재생성 없이 검증만 수행합니다.

@seonghobae
seonghobae enabled auto-merge (squash) August 16, 2026 12:09
@coderabbitai

coderabbitai Bot commented Aug 16, 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: 2 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: 7cfa39d9-d040-410c-836f-40806bd77563

📥 Commits

Reviewing files that changed from the base of the PR and between 8d141d5 and 1be7698.

📒 Files selected for processing (7)
  • ARCHITECTURE.md
  • CHANGELOG.md
  • docs/doctoring/orphaned-workflow-lifecycle.md
  • schemas/examples/cwl-workflow-lifecycle-ledger-v1.example.json
  • scripts/ci/inventory_orphaned_workflows.py
  • scripts/ci/test_strix_quick_gate.sh
  • tests/test_inventory_orphaned_workflows.py
📝 Walkthrough

Walkthrough

읽기 전용 GitHub Actions 워크플로 인벤토리 스크립트를 추가했습니다. 기본 브랜치 SHA와 워크플로 레지스트리를 비교하고 상태를 분류합니다. 불완전한 입력과 API 응답은 실패 처리합니다. 결과는 JSON 원장으로 출력하며 관련 테스트와 운영 문서를 추가했습니다.

Changes

워크플로 수명주기 인벤토리

Layer / File(s) Summary
입력 및 검증 계약
scripts/ci/inventory_orphaned_workflows.py, tests/test_inventory_orphaned_workflows.py
금지된 레지스트리 변경, 잘못된 자격 증명, SHA, 경로, HTTP 응답, 페이지네이션 및 JSON 입력을 거부합니다.
워크플로 수집 및 분류
scripts/ci/inventory_orphaned_workflows.py, tests/test_inventory_orphaned_workflows.py
기본 브랜치 트리와 Actions 워크플로 페이지를 비교하여 present, orphan, dynamic, disabled, unresolved 상태를 분류합니다.
조직 원장 및 CLI 출력
scripts/ci/inventory_orphaned_workflows.py, schemas/examples/cwl-workflow-lifecycle-ledger-v1.example.json, tests/test_inventory_orphaned_workflows.py, scripts/ci/organization_commercial_readiness_loop.py
조직별 분류 결과와 owner issue를 병합하고 정렬된 JSON 원장을 출력합니다. 활성 orphan 처리, 오류 종료 코드, 모듈 실행 동작을 검증합니다.
운영 문서 및 변경 기록
docs/doctoring/orphaned-workflow-lifecycle.md, ARCHITECTURE.md, CHANGELOG.md
수명주기 분류 기준, fail-closed 조건, 읽기 전용 경계, 운영 절차 및 변경 내역을 기록합니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🔵 Low · up to 8d141

The PR adds a read-only workflow-identity inventory without changing registry state. It is mergeable with owner follow-up for bounded risks: audit records may overstate inspection coverage, rollback instructions omit some related files, and usage documentation should accurately describe fixture-based input.

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant inventory_orphaned_workflows
  participant GitHub_Actions_API
  participant Repository_Tree
  Operator->>inventory_orphaned_workflows: JSON payload와 CLI 옵션 전달
  inventory_orphaned_workflows->>GitHub_Actions_API: 워크플로 페이지 조회
  GitHub_Actions_API-->>inventory_orphaned_workflows: 워크플로 상태, 경로, 페이지네이션 반환
  inventory_orphaned_workflows->>Repository_Tree: 기본 브랜치 SHA의 파일 트리 조회
  Repository_Tree-->>inventory_orphaned_workflows: 저장소 YAML 경로 반환
  inventory_orphaned_workflows-->>Operator: 분류된 JSON ledger와 종료 코드 반환
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 읽기 전용 orphaned GitHub Actions workflow identity inventory 추가라는 변경의 핵심을 정확하고 간결하게 설명합니다.
Docstring Coverage ✅ Passed Docstring coverage is 92.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 50 functions across 3 files. (4 skipped: 4 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/orphaned-workflow-lifecycle-inventory

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

Copy link
Copy Markdown
Contributor Author

Exact current-head evidence for f7a457240c3871a09dc3c231235a2db8e893bc79: orphaned-workflow inventory tests passed (18 passed), the inventory module has 100% statement/branch coverage and 100% interrogate docstring coverage, compileall and diff check pass. It is read-only, SHA-bound, pagination-fail-closed, rejects duplicate JSON keys, and forbids registry mutation/Copilot credentials. Protected checks/review still govern merge.

@seonghobae
seonghobae force-pushed the feat/orphaned-workflow-lifecycle-inventory branch from f7a4572 to cbb0784 Compare August 19, 2026 15:22
@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head evidence: rebased the orphaned-workflow lifecycle inventory onto main bbedc1a. Exact head cbb0784. Inventory contract tests: 18 passed; git diff --check passed. Protected hosted checks remain; no bypass used.

Copy link
Copy Markdown
Contributor Author

Fresh Inkspan consumer audit exposes a current exact-head routing contract gap in this existing #945 owner PR; no Inkspan-local scanner workaround is correct.

Exact source owner: #1026 cbb07849c5e84af7017491060de6a7516ddb935d against protected .github/main@bbedc1a51ec1a2421f129955c629b3cd0507a4ec. The current scripts/ci/inventory_orphaned_workflows.py hard-codes KNOWN_OWNER_ISSUES for only appguardrail, clearfolio, and disksage; owner_issue_for(repository) is then consulted only for orphan_active, and the emitted record omits owner_issue when that lookup returns None.

That proposition now conflicts with the live #945 authority itself: #945 already records Inkspan as a confirmed fleet reproduction (48 registry records in the recorded snapshot, sampled active apply-preparse-envelope-limits.yml absent from protected main) with existing owner ContextualWisdomLab/inkspan#278. Fresh Inkspan protected truth is main@3b38ead2d00f44eb578d0689087b9293b3dabe1e; #278 remains open and its read-only detector owner is Draft #279. The current #1026 classifier will correctly classify an Inkspan missing active repository workflow as orphan_active but will not route that record to #278. That violates #945 acceptance item 9 (open/update bounded repository owner issues) and makes the ledger incomplete as remediation evidence even though classification itself is correct.

Falsifiable RCA: owner routing is encoded as a stale three-repository constant rather than being complete for the current centrally accepted fleet-owner registry. This is central source ownership; Inkspan must not duplicate or patch the shared classifier.

Test-first acceptance for this PR: add a RED fixture containing repository inkspan, exact bound default-branch SHA, and an active missing .github/workflows/apply-preparse-envelope-limits.yml; require the resulting orphan_active record to carry exactly ContextualWisdomLab/inkspan#278. Keep a negative control for a repository with no reviewed owner so the classifier does not invent an issue. Smallest GREEN is to extend the versioned explicit owner registry with every owner already accepted by #945 (including Inkspan); the more maintainable alternative is a validated versioned owner-map input, but it has larger schema/blast radius. Do not infer issue numbers from naming, auto-create owners inside the read-only scanner, or make absent owner metadata convert orphan_active to passing.

Current exact-head workflow evidence is not acceptance-clean independently of this source defect: OSV 32269646751, SAST 32269640813, SBOM 32269640791, Secret Scan 32269640713, Scorecard 32269640747, and Security Scan 32269640859 are terminal success, while Python Security 32269640812 and CodeQL 32269640687 are still queued at this refetch; formal reviews are 0. Preserve the read-only/no-registry-mutation boundary and exact-SHA/pagination fail-closed behavior while repairing owner routing.

@seonghobae
seonghobae force-pushed the feat/orphaned-workflow-lifecycle-inventory branch from f4f0f81 to 7121132 Compare August 20, 2026 00:49
@seonghobae

Copy link
Copy Markdown
Contributor Author

Rebased orphaned workflow lifecycle inventory onto current main@c47bee59. Exact head: 7121132. The read-only scanner binds every classification to an unchanged exact default-branch SHA, paginates with count/ID checks, rejects traversal/encoded paths and COPILOT_GITHUB_TOKEN, distinguishes active/disabled/dynamic/unresolved identities, and preserves owner issue evidence. Evidence: 18 tests passed, interrogate 100%, compileall and diff check passed.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@OpenCode Please review exact current head 7121132 against base main@c47bee591c3d95bd305f2130833ed3a4780d2d1d.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Verified the orphaned-workflow lifecycle inventory on exact HEAD 7121132 against c47bee5: 18 focused tests, interrogate 100%, compileall, and diff --check. The ledger/inventory remains read-only and bounded. Please review this exact head.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent review exact current head 7121132 against base c47bee5; inspect the orphaned identity classification, ledger schema, and read-only contract.

Add a read-only classifier that binds advertised GitHub Actions
identities to the exact protected default-branch SHA, fail-closes on
pagination or visibility defects, and refuses registry mutation.

Addresses #945.
@seonghobae
seonghobae force-pushed the feat/orphaned-workflow-lifecycle-inventory branch from 7121132 to bbd7fa9 Compare August 20, 2026 04:50
@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent review exact current head bbd7fa9 against protected base 2cce96f. Rebased the read-only orphaned workflow inventory onto current main; verified 18 focused tests, compileall, interrogate, and diff --check. Confirm exact default-branch SHA binding, bounded pagination, traversal/encoded-path/COPILOT token rejection, identity classification, and ledger evidence on this head.

@seonghobae
seonghobae enabled auto-merge (squash) August 20, 2026 06:57
@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head validation for exact commit 1e84d65f38b2112c56d9ce7828a041ad3c198b07: orphaned-workflow inventory tests pass (18 passed), owned statement/branch coverage is 100%, interrogate docstring coverage is 100%, and diff checks pass. Please have @opencode-agent independently review this exact HEAD and confirm current protected Checks before merge; no stale approval is sufficient.

@opencode-agent
opencode-agent Bot disabled auto-merge August 20, 2026 09:59
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact-head local verification for 8d08bac8e5d1a21b04a8d62a72012f9eb76bc07b: tests/test_inventory_orphaned_workflows.py passed (18 passed); owned source statement/branch coverage passed at 100% (264 statements, 132 branches); interrogate passed at 100%; compileall and git diff --check passed. The PR remains read-only and refuses registry mutation. Hosted coverage-evidence is still queued. The scheduler check cancellation is from cancelled run 32420958336, not a code failure; no exact-head approval or merge was performed.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact-head evidence for 271ad3a: corrected the ARCHITECTURE.md section order identified by Devin. The hourly product-caller note now remains under the hourly NVIDIA NIM repair gate. Local verification passed: 18 inventory tests; 264 statements / 132 branches at 100% for the production inventory module; interrogate, compileall, and git diff --check. Hosted checks must be regenerated for this SHA; no approval or merge is claimed.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Additional exact-head evidence for 271ad3a: complete central suite passed 1,301 tests plus 16 subtests; aggregate production statement/branch coverage is 100% (8,328 statements / 3,260 branches). The repository-wide interrogate run is 99.9% solely because the pre-existing GitHubClient.init docstring is owned by #1189; the changed inventory module remains 100%. I did not duplicate that separate PR scope. No approval or merge is claimed.

@seonghobae
seonghobae enabled auto-merge (squash) August 21, 2026 20:44
@opencode-agent
opencode-agent Bot disabled auto-merge August 21, 2026 20:53
@opencode-agent opencode-agent Bot added area: ci-cd CI, GitHub Actions, checks, release, or supply chain priority: medium Normal-priority or P2 work scope: product-gap Customer-visible product gap status: blocked Blocked by conflict, dependency, or required prerequisite type: feature New or expanded product capability labels Aug 22, 2026
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 43 minutes.

Check out review usage here.

View limit details

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.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 4e781f89-a54b-4442-bf5a-feb76e3be42d

📥 Commits

Reviewing files that changed from the base of the PR and between f2f91b8 and d17ff23.

📒 Files selected for processing (13)
  • .github/workflows/workflow-lifecycle-inventory-quality-ci.yml
  • .github/workflows/workflow-lifecycle-inventory.yml
  • ARCHITECTURE.md
  • CHANGELOG.md
  • docs/doctoring/orphaned-workflow-lifecycle.md
  • schemas/examples/cwl-workflow-lifecycle-ledger-v1.example.json
  • scripts/ci/inventory_orphaned_workflows.py
  • scripts/ci/test_strix_quick_gate.sh
  • scripts/ci/workflow_lifecycle_operator.py
  • tests/test_inventory_orphaned_workflows.py
  • tests/test_pr_review_fix_scheduler_direct_rca_regressions.py
  • tests/test_pr_review_fix_scheduler_rest_workflow_identity.py
  • tests/test_workflow_lifecycle_inventory_workflow.py

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.

@opencode-agent opencode-agent 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.

Pull request overview

OpenCode reviewed the current-head mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch feat/orphaned-workflow-lifecycle-inventory cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into feat/orphaned-workflow-lifecycle-inventory, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 1026 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:feat/orphaned-workflow-lifecycle-inventory
# rebase path only: git push --force-with-lease origin HEAD:feat/orphaned-workflow-lifecycle-inventory
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 1be76989887ab772e3ce0d2e0c7f22d3ca98dd94
  • Workflow run: 32768394298
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 1be76989887ab772e3ce0d2e0c7f22d3ca98dd94
  • Workflow run: 32777281829
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode reviewed the current-head mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch feat/orphaned-workflow-lifecycle-inventory cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into feat/orphaned-workflow-lifecycle-inventory, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 1026 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:feat/orphaned-workflow-lifecycle-inventory
# rebase path only: git push --force-with-lease origin HEAD:feat/orphaned-workflow-lifecycle-inventory
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 1be76989887ab772e3ce0d2e0c7f22d3ca98dd94
  • Workflow run: 32777281829
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading

Merge Conflict Guidance

  • Current merge state: DIRTY
  • Base branch: main
  • Head branch: feat/orphaned-workflow-lifecycle-inventory
  • Fix direction: merge or rebase origin/main into feat/orphaned-workflow-lifecycle-inventory, resolve conflict markers in the changed files, rerun the focused checks, then push the same branch.
  • Repair commands:
gh pr checkout 1026 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:feat/orphaned-workflow-lifecycle-inventory
# rebase path only: git push --force-with-lease origin HEAD:feat/orphaned-workflow-lifecycle-inventory

@opencode-agent opencode-agent 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.

Pull request overview

OpenCode reviewed the current-head mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch feat/orphaned-workflow-lifecycle-inventory cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into feat/orphaned-workflow-lifecycle-inventory, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 1026 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:feat/orphaned-workflow-lifecycle-inventory
# rebase path only: git push --force-with-lease origin HEAD:feat/orphaned-workflow-lifecycle-inventory
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 1be76989887ab772e3ce0d2e0c7f22d3ca98dd94
  • Workflow run: 32777281829
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (3 files)"]
  S1 --> I1["repository behavior"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["required checks"]
  Evidence --> S2["Docs: orphaned-workflow-lifecycle.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["docs review"]
  Evidence --> S3["CI script (3 files)"]
  S3 --> I3["review and security gate shell path"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_inventory_orphaned_workflows.py"]
  S4 --> I4["regression suite"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["targeted test run"]
Loading

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

Fresh current-main convergence pass: keep this lane non-merge-ready until the latest live-inventory review findings are repaired on the existing owner branch. Required fixes: (1) repository_inventory_complete=true must require independently verifiable organization-wide repository visibility, not merely a syntactically complete page sequence from a possibly repository-restricted token; fail closed when full visibility cannot be proven. (2) Integrate exactly one bounded retry for transport/server 5xx into the actual _live_get/GitHubClient.request production path; do not retry permission/visibility/malformed responses. (3) Validate every recursive git-tree entry before filtering: each entry must be an object with a recognized type and valid string path; malformed/unknown entries must abort rather than become negative source evidence. Also preserve API receipts on failed sweeps, move fixture completeness rejection before classification, and split workflow-disable/issue-write primitives out of the read-only scanner module into a separately reviewed operator boundary. Add focused tests for a visibility-restricted-but-well-paginated repo listing, one 5xx then success, malformed tree entries, failure receipt upload, early incomplete-fixture rejection, and absence of mutation primitives from the scanner. Do not broaden the workflow token to hide these evidence-boundary defects.

@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 6 new potential issues.

Devin Review

Comment on lines +148 to +152
visible_names = {item.get("full_name") for item in repositories}
if (
len(visible_names) != len(repositories)
or len(repositories) != public_repos + private_repos
):

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.

🟡 Repository renames bypass completeness proof

collect_live_organization validates only unique-name counts after page-number pagination. A concurrent rename can omit one repository while preserving the accepted total.

Prompt for agents
The repository completeness check in collect_live_organization cannot establish a stable inventory from one page-number traversal plus a total count. A repository rename during sorted pagination can produce a same-sized unique list that omits another repository. Add a stability proof, such as repeating the complete paginated repository listing and requiring the canonical repository identity set to match before scanning, then revalidating it before emission. Retain the organization-wide total check and add a regression fixture that shifts an item across a page boundary without changing the total.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +78 to +84
created = client.request(
f"/repos/ContextualWisdomLab/{repository}/issues",
method="POST",
payload={
"title": "Disable orphaned workflow registry identity",
"body": body,
},

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.

🟡 Repeated publication duplicates owner issues

publish_owner_issue always creates an issue without a static route. Reprocessing the same ledger creates another identical owner issue.

Prompt for agents
Make publish_owner_issue idempotent for repositories absent from KNOWN_OWNER_ISSUES. Before creating an issue, locate an existing lifecycle issue using a stable marker or durable ledger mapping and comment on or return that issue instead. Ensure repeated publication of the same ledger digest does not create duplicate issues, and add a regression test covering two calls for one unknown repository.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +698 to +702
try:
text = write_ledger(ledger, Path(args.output) if args.output else None)
except (FileNotFoundError, OSError) as exc:
print(f"ERROR: unable to write ledger: {exc}", file=sys.stderr)
return 2

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.

🔍 Ledger write failures lack evidence

A ledger write error bypasses failure_output. The always-upload step then lacks both a ledger and structured failure record.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

ledger_sha = record.get("default_branch_sha")
if not isinstance(repository, str) or not isinstance(workflow_id, int):
raise InventoryError("operator record identity is malformed")
assert_default_branch_bound(ledger_sha, confirmed_head_sha)

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.

🟥 Stale evidence authorizes workflow disablement

disable_confirmed_orphan trusts a caller-supplied head SHA without a live read. Stale orphan evidence can disable a workflow restored on the current branch.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +31 to +32
if not isinstance(repository, str) or not isinstance(workflow_id, int):
raise InventoryError("operator record identity is malformed")

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.

🟨 Mutation target lacks ledger validation

disable_confirmed_orphan accepts any string repository and integer workflow ID. Untrusted records can redirect the privileged API request beyond a valid ledger identity.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +52 to +58
if (
record.get("classification") != "orphan_active"
or HEX_SHA256.fullmatch(ledger_sha256) is None
):
raise InventoryError(
"issue publication requires an orphan_active and ledger digest"
)

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.

🟨 Fabricated records gain trusted issue evidence

publish_owner_issue never verifies that ledger_sha256 covers the supplied record. Fabricated workflow details can be published as integrity-bound evidence.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

This is now a high-leverage #1531 queue-lifecycle owner, but the branch predates #1546 and currently mixes its inventory feature with scheduler coverage files that are canonically owned by #1567 (tests/test_pr_review_fix_scheduler_direct_rca_regressions.py, tests/test_pr_review_fix_scheduler_rest_workflow_identity.py). @opencode-agent converge this PR non-destructively as a clean child of #1567: merge #1567's live head into this branch, retarget the base to fix/main-coverage-gap-scheduler-rest-and-live-head, and keep the base-relative delta to workflow-lifecycle inventory/operator workflows, inventory implementation/tests/schema, necessary Strix quality contract, ARCHITECTURE/CHANGELOG/APA-7 doctoring/baseline traceability. Remove duplicated scheduler-test ownership if those files become identical to the parent. Preserve #1546 exact-head reviewer lifecycle, never mutate/disable Actions registry entries from this read-only inventory PR, and add a dated docs/product-technical-gap-baseline.md entry linking current 700+ queued-run incident evidence to orphan-active inventory acceptance. Fresh exact-head OpenCode/Noema review after restack; no predecessor evidence transfers.

seonghobae added a commit that referenced this pull request Sep 2, 2026
…rchestrator#1026

Found #1026 already merged, delivering both the priority audit-staleness fix
and the noted secondary color-coded-feedback improvement for model_groups'
save/delete handlers. Diffed the still-open duplicate #1011 against #1026
before closing it: same fix, different implementation (CSS classes vs inline
style), functionally identical outcome, now genuinely CONFLICTING against
main. Closed #1011 with evidence per repair-not-close policy (full-delta
successor case).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
claude and others added 2 commits September 4, 2026 03:23
# Conflicts:
#	CHANGELOG.md
#	scripts/ci/test_strix_quick_gate.sh
…entory)

One conflicted file: scripts/ci/test_strix_quick_gate.sh, one conflict block.

Block classification (line by line):
- 'scopes workflow_run concurrency to the completed review PR' -> DROPPED.
  main removed the workflow_run trigger from pr-review-merge-scheduler.yml
  entirely (merge-base and branch both had it 14x; main has 0x) and inverted
  the contract to assert_file_not_contains 'workflow_run:' and
  assert_file_not_contains 'github.event.workflow_run'. Keeping the branch's
  assertion would have put two mutually contradictory assertions in one gate.
- 'isolates ... hourly organization sweep' vs 'isolates repository-local
  recovery from PR runs' -> took main's wording; same assertion string, main's
  current message.
- 'keeps manual queue scans isolated per repository dispatch target' -> KEPT.
  This one line is this PR's entire contribution to the file (branch diff vs
  merge-base: 1 file changed, 1 insertion). main has no equivalent assertion.

Loss check: the resolved file differs from main's version by exactly that one
line and nothing else (diff /tmp/theirs.sh -> 1568a1569, single '>' line).

Evidence:
- uvx ruff check --select F821 scripts/ci tests: All checks passed
- full suite, branch head 2cbd370 (unmerged): 2825 passed, 0 failed
- full suite, this merge:                      2946 passed, 0 failed
  (failure-name diff empty on both sides with non-zero denominators)
- PR's own oracle, tests/test_inventory_orphaned_workflows.py +
  tests/test_workflow_lifecycle_inventory_workflow.py: 47 passed
- isolated run of the resolved gate function
  assert_pr_review_merge_scheduler_uses_github_actions_bot_token: 0 failures
- negative control 1: deleting the repo-dispatch scoping line from the
  workflow makes the KEPT assertion fail (1 failure, named) -> it has real
  detection power, it is not decorative
- negative control 2: re-adding the DROPPED workflow_run assertion makes it
  fail against current main (1 failure, named) -> dropping it was required,
  not a convenience
- coverage report: TOTAL 100%; interrogate: PASSED (minimum 100.0%)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

main 병합 완료 — 충돌 1건 해결 (d17ff23c)

충돌 파일은 scripts/ci/test_strix_quick_gate.sh 하나, 블록도 하나였습니다.

한 줄 요약: 이 PR이 그 파일에 넣은 기여 한 줄은 그대로 살렸고, main이 기능 자체를 없앤 단언 하나는 폐기했습니다.

판정 근거
scopes workflow_run concurrency to the completed review PR 폐기 main이 pr-review-merge-scheduler.yml에서 workflow_run 트리거를 통째로 제거했습니다(merge-base·이 브랜치 14회 → main 0회). 그리고 계약을 assert_file_not_contains 'workflow_run:' / assert_file_not_contains 'github.event.workflow_run'로 뒤집었습니다. 이 단언을 남겼다면 한 게이트 안에 서로 모순되는 단언 두 개가 공존합니다.
isolates the hourly organization sweep…isolates repository-local recovery from PR runs main 문구 채택 단언 문자열은 동일, 메시지만 현행판
keeps manual queue scans isolated per repository dispatch target 보존 merge-base 대비 이 브랜치의 해당 파일 diff는 1 file changed, 1 insertion — 이 한 줄이 기여 전부입니다. main에는 대응 단언이 없습니다.

손실 없음의 산술적 확인: 해결본을 main 판본과 직접 diff하면 1568a1569 한 줄뿐입니다. 즉 main의 현행 내용을 전부 취하고 이 PR의 기여 한 줄만 더한 상태입니다.

검증

  • uvx ruff check --select F821 scripts/ci tests — All checks passed
  • 전체 스위트, 병합 전 브랜치 헤드 2cbd3708: 2825 passed / 0 failed
  • 전체 스위트, 이 병합: 2946 passed / 0 failed (양쪽 실패 집합 공집합, 분모 2825·2946로 실재하는 측정)
  • 이 PR 고유 오라클 tests/test_inventory_orphaned_workflows.py + tests/test_workflow_lifecycle_inventory_workflow.py: 47 passed
  • 해결한 게이트 함수 assert_pr_review_merge_scheduler_uses_github_actions_bot_token 격리 실행: 0 failures
  • 네거티브 컨트롤 ① 워크플로에서 repo-dispatch 스코프 줄을 지우면 → 보존한 단언이 이름을 찍고 실패(1건). 장식이 아니라 실제 탐지력이 있습니다.
  • 네거티브 컨트롤 ② 폐기한 workflow_run 단언을 되살리면 → 현행 main에서 이름을 찍고 실패(1건). 폐기는 편의가 아니라 필수였습니다.
  • coverage report TOTAL 100%, interrogate PASSED (minimum 100.0%)

브랜치 히스토리는 fast-forward이며 force push는 없습니다.

🤖 Generated with Claude Code

@seonghobae seonghobae added the enhancement New feature or request label Sep 7, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-cd CI, GitHub Actions, checks, release, or supply chain enhancement New feature or request priority: medium Normal-priority or P2 work scope: product-gap Customer-visible product gap status: blocked Blocked by conflict, dependency, or required prerequisite type: feature New or expanded product capability

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants