Skip to content

ci(noema): keep sanitized sidecar evidence, including discovery timing, on successful runs - #2326

Draft
seonghobae wants to merge 2 commits into
mainfrom
fix/noema-sidecar-evidence-always
Draft

seonghobae wants to merge 2 commits into
mainfrom
fix/noema-sidecar-evidence-always

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In noema-review.yml, the "Upload contextual-orchestrator sidecar evidence" step ran only under if: failure() && env.PR_NUMBER != ''. Every successful Noema run therefore discarded the sanitized sidecar stderr. The vendored pin 767e67fb and scripts/ci/contextual_orchestrator_review_launcher.py (_configure_sidecar_logging, DEBUG by default) already emit the http_request and discovery_complete lines, so the missing piece is the upload. No CO pin bump or --log-level change is needed. contextual-orchestrator#1218 does not change the deployed Noema path.

Change

  • Head a403d73b also allowlists two sanitizer lines: discovery_result account=<provider> model_count=N elapsed_ms=X (DEBUG) and discovery_complete providers=N models=N errors=N (INFO) from model_discovery.py at pin 767e67fb. They are kept with the timestamp, and only the provider name and bounded numbers survive, so pre-healthz startup can be split into discovery and preflight. Scope was agreed with the contextual-orchestrator lead, who is reviewing independently.
  • The step condition becomes if: always() && env.PR_NUMBER != '', the same gate Strix uses for strix-reports. The step name drops "on failure".
  • Unchanged: files (strix_runs/contextual-orchestrator-sidecar.stderr.log, …-preflight.json), artifact name noema-sidecar-evidence, the pinned actions/upload-artifact@043fb46d…, if-no-files-found: ignore, 5-day retention, and the step position (after "Prepare Noema model verdict", before the publication token refresh).
  • Exposure is unchanged. The file is the sanitizer's bounded allowlist output, which is already uploaded on failure and by Strix on every outcome.
  • The contract test is renamed to test_noema_review_uploads_sidecar_evidence_on_every_outcome, asserts always(), and asserts that failure() no longer appears. One CHANGELOG entry is added.

Evidence

  • pytest tests/test_noema_orchestrator_workflow_contract.py: 12 passed.
  • The 11 other test files that reference noema-review.yml (runner image, required inventory, ruleset audit, queue contract, docs-only admission, token lifetime, gate, and more): 293 passed, 2 skipped. tests/test_pr_review_merge_scheduler.py -k noema: 1 passed.
  • test_sidecar_stream_sanitizer_admits_discovery_timing_events: fails on the previous sanitizer, passes now. tests/test_contextual_orchestrator_review_runtime_preflight.py: 136 passed. The 13 test files that reference the sanitizer or noema-review.yml: 773 passed, 2 skipped. Sanitizer module coverage and interrogate are both 100%.
  • Full suite on 223106b: 3,394 passed and interrogate 100%. Total coverage was 99%, with the missing lines in files this PR does not touch (actions_queue_health*, noema_review_document, …). Hosted CI decides.

Conflicts

Trust boundary

This is a pull_request_target required workflow, so the new condition takes effect for consumer PRs only after merge, on the base branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LeLbwEgYXzCzpaFMTHDcBS

Summary by CodeRabbit

  • 개선 사항

    • 워크플로 실행이 성공, 실패 또는 취소된 경우에도 사이드카 증거 자료가 보존됩니다.
    • 보존되는 자료에는 로그와 사전 점검 결과가 포함됩니다.
    • 정제된 로그에서 검색 과정의 완료 시점과 처리 통계를 확인할 수 있습니다.
  • 문서

    • 사이드카 증거 자료 보존 조건과 검색 과정 정보 기록 변경 사항을 변경 로그에 반영했습니다.

The noema-sidecar-evidence upload ran only under failure(), so every
successful Noema run discarded the sanitized sidecar stderr that already
carries the DEBUG http_request/discovery_complete lines from pin 767e67fb.
Match Strix's always() gate; files, pin, name and retention are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeLbwEgYXzCzpaFMTHDcBS
@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Understand this PR’s impact

Explore downstream dependencies and potential security impact with Blast Radius.

View blast radius →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 12b75f3e-5087-429a-9e60-50d720fa64ba

📥 Commits

Reviewing files that changed from the base of the PR and between 223106b and a403d73.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • scripts/ci/sanitize_contextual_orchestrator_sidecar_stream.py
  • tests/test_contextual_orchestrator_review_runtime_preflight.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Sidecar 증거 업로드 조건이 failure()에서 always()로 변경되었습니다. Sanitizer가 discovery 타이밍 이벤트를 허용합니다. 계약 테스트와 변경 로그가 새 동작을 반영합니다.

Changes

Sidecar 증거 및 discovery 타이밍

Layer / File(s) Summary
모든 종료 상태의 증거 업로드 및 계약 검증
.github/workflows/noema-review.yml, tests/test_noema_orchestrator_workflow_contract.py, CHANGELOG.md
워크플로 단계가 always() && env.PR_NUMBER != '' 조건에서 실행됩니다. 단계 이름과 계약 테스트가 변경되었습니다. 기존 아티팩트 이름, 파일 경로, 보존 기간, 업로드 설정은 유지됩니다. 변경 로그가 성공 실행의 증거 보존 동작을 기록합니다.
Discovery 타이밍 이벤트 정화
scripts/ci/sanitize_contextual_orchestrator_sidecar_stream.py, tests/test_contextual_orchestrator_review_runtime_preflight.py
Sanitizer가 discovery_result와 discovery_complete 이벤트의 제한된 계정, 개수, 소요 시간 필드를 허용합니다. 테스트가 허용된 필드와 추가 필드, 허용되지 않은 계정 및 비숫자 값의 거부를 검증합니다.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (1 skipped: 1 …
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 성공한 실행을 포함한 모든 종료 상태에서 정화된 사이드카 증거를 보존하고 discovery timing을 포함하는 핵심 변경을 정확하고 간결하게 설명합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

The sanitizer dropped model_discovery.py's discovery_result (DEBUG,
per-provider elapsed_ms) and discovery_complete (INFO) lines, so the
Noema sidecar artifact could not split pre-healthz startup into discovery
and preflight. Allowlist both with the timestamp, keeping only the
provider name and bounded numbers, and correct the CHANGELOG claim that
discovery_complete already reached the sanitized file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeLbwEgYXzCzpaFMTHDcBS
@seonghobae seonghobae changed the title ci(noema): keep sanitized sidecar evidence on successful runs ci(noema): keep sanitized sidecar evidence, including discovery timing, on successful runs Sep 21, 2026

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[central CI evidence contract — exact a403d73b034e3eeaf7b89dd4487ad32f1fa4761c]

failure()→always() 방향은 성공 실행의 진단 증거를 보존한다는 목적과 맞습니다. 다만 이 exact head는 아직 “successful Noema run keeps sidecar evidence”를 fail-closed contract로 만들지 못했습니다.

핵심은 upload step이 계속 if-no-files-found: ignore라는 점입니다. sidecar stderr/preflight 생성 경로가 rename/path/logging regression으로 조용히 사라져도 Noema verdict가 성공하면 upload step도 성공하고 artifact가 0개인 채 required workflow가 GREEN이 될 수 있습니다. 현재 test도 YAML에 always()가 있는지만 확인하므로 이 failure mode를 잡지 못합니다. 이번 PR의 buyer-visible 목적 자체가 evidence retention인 만큼, 성공 verdict + admitted sidecar 경로에서는 두 파일(또는 명시된 required subset)의 존재/비어 있지 않음/expected schema를 먼저 검증하고 누락 시 evidence gate를 실패시켜야 합니다. sidecar가 애초에 실행되지 않는 명시적 context가 있다면 그 context만 별도 branch로 ignore를 허용하십시오.

Realistic RED: otherwise-successful Noema fixture에서 stderr 또는 preflight 파일을 하나씩 제거/잘못된 경로로 이동시키고 현재 workflow가 녹색으로 지나가는 것을 재현 → GREEN에서 evidence-presence contract가 nonzero로 막아야 합니다. Hosted acceptance도 이 exact generation의 실제 successful run에서 noema-sidecar-evidence artifact가 존재하고 두 payload를 포함하는지 확인해야 합니다. 단순 unit/YAML assertion으로는 ‘kept’가 증명되지 않습니다.

또한 body의 “Exposure is unchanged”는 data category 관점에서는 Strix/failure path와 같을 수 있지만 exposure frequency는 failure-only에서 every outcome으로 넓어집니다. 따라서 sanitizer allowlist test에 gateway/provider secret, Authorization/header, URL/query, prompt/user payload, arbitrary exception text 같은 negative controls를 유지하고, artifact visibility/retention(5 days)을 SECURITY/THREAT_MODEL 또는 해당 workflow contract에 명시해 주세요. request_id/provider account label을 보존하는 것이 의도된 telemetry인지도 contract에 고정하는 편이 좋습니다.

현재 hosted exact-head runs(35611933746, 35611934408, 35611934414, 35611933749, 35611933715)은 pending/queued라 release evidence도 아직 없습니다.

판정: direction PASS candidate / success-path evidence-presence FAIL / exposure-doctoring PENDING / exact-head hosted acceptance PENDING.

@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 product diff. Coverage is a separate gate.

Changed files

  • .github/workflows/noema-review.yml — GitHub Actions review job
  • CHANGELOG.md — repository behavior
  • scripts/ci/sanitize_contextual_orchestrator_sidecar_stream.py — review and security gate shell path
  • tests/test_contextual_orchestrator_review_runtime_preflight.py — regression suite
  • tests/test_noema_orchestrator_workflow_contract.py — regression suite

Changed behavior

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: noema-review.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: noema-review.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Repository file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: CHANGELOG.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["CI script: sanitize_contextual_orchestrator_sidecar_stream.py"]
  S3 --> I3["review and security gate shell path"]
  I3 --> R3["Review risk: CI script: sanitize_contextual_orchestrator_sidecar_stream.py"]
  R3 --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_contextual_orchestrator_review_runtime_preflight.py (2 files)"]
  S4 --> I4["regression suite"]
  I4 --> R4["Review risk: Test: test_contextual_orchestrator_review_runtime_preflight.py (2 files)"]
  R4 --> V4["targeted test run"]
Loading

Findings

No source-backed product finding is synthesized from the coverage gate. A coverage miss belongs in the status comment.

  • Head SHA: a403d73b034e3eeaf7b89dd4487ad32f1fa4761c
  • Workflow run: 35663552145
  • Workflow attempt: 1
  • Coverage gate: failure

Review outcome

Coverage is a gate, not the review. This body reviews the changed product files.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: noema-review.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: noema-review.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Repository file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: CHANGELOG.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["CI script: sanitize_contextual_orchestrator_sidecar_stream.py"]
  S3 --> I3["review and security gate shell path"]
  I3 --> R3["Review risk: CI script: sanitize_contextual_orchestrator_sidecar_stream.py"]
  R3 --> V3["bash -n plus Strix self-test"]
  Evidence --> S4["Test: test_contextual_orchestrator_review_runtime_preflight.py (2 files)"]
  S4 --> I4["regression suite"]
  I4 --> R4["Review risk: Test: test_contextual_orchestrator_review_runtime_preflight.py (2 files)"]
  R4 --> V4["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

Coverage evidence did not pass, so approval is blocked. The formal pull-request review is the source-backed diff review, not this status comment.

Copy link
Copy Markdown
Contributor Author

Admission correction — exact current head a403d73b034e3eeaf7b89dd4487ad32f1fa4761c was re-fetched immediately before this transition. The PR remains Open and its branch, commits, reviews, and valid delta are preserved, but it is not merge-admissible: 활성 CHANGES_REQUESTED 1개; terminal workflow failure: Python Security:failure, CodeQL PR:failure. Moving it to Draft/Proposed records the live blocker without retiring or closing the work. Return it to Ready only after the same exact head (or a non-destructive reconciled successor) is mergeable, has no substantive unresolved review state, and has terminal required Checks.

@seonghobae
seonghobae marked this pull request as draft September 26, 2026 15:28

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant