Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/noema-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -841,8 +841,8 @@ jobs:
}' | gh api -X POST "repos/${TARGET_REPOSITORY}/dispatches" --input -
echo "::notice::Scheduled Noema transport continuation re-dispatch for ${TARGET_REPOSITORY}#${PR_NUMBER} at ${EXPECTED_HEAD_SHA} (attempt ${NEXT_ATTEMPT})."

- name: Upload contextual-orchestrator sidecar evidence on failure
if: failure() && env.PR_NUMBER != ''
- name: Upload contextual-orchestrator sidecar evidence
if: always() && env.PR_NUMBER != ''
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-sidecar-evidence
Expand Down
25 changes: 25 additions & 0 deletions docs/noema-sidecar-evidence-1218.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Noema startup evidence for contextual-orchestrator PR #1218

On 2026-09-27, run `36025318452`, attempt 3, job `108389560765`
was inspected at consumer head `2fed942d378cd959250f648a16b35276279c9603`.
The job used gateway pin `767e67fbc6b881a452761f32abb69b9971b9b03b`.
Dependencies installed successfully. At 2026-09-26T12:37:08Z the sidecar
started; no health/preflight-ready confirmation followed. The job was cancelled
at 18:35:14Z, approximately six hours after admission. This does not establish
that a Noema review request or any particular provider attempt occurred.

Artifact `10877250808` was created on 2026-09-25T17:04:14Z and belongs to an
earlier attempt. It must not be attributed to attempt 3 merely because the
workflow run ID and consumer head are equal.

The workflow uploaded its two existing sanitized evidence files only under
`failure()`. Using `always()` preserves those same files after successful,
failed and normally cancelled execution, without collecting raw provider logs.
The pinned uploader, file allowlist, five-day retention and absent-file behavior
remain intact. A hard runner timeout may prevent cleanup/upload entirely; this
change cannot recover the missing attempt-3 evidence or prove its internal
startup cause. Gateway inference timeouts must not be invented to hide it.

Verification: the changed workflow contract fails on the previous source;
the Noema workflow contract suite and actionlint verify the revised step.
Hosted execution and independent review remain required before integration.
17 changes: 7 additions & 10 deletions tests/test_noema_orchestrator_workflow_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,19 +493,16 @@ def test_noema_review_job_has_no_job_level_timeout() -> None:
), "the two-hour-per-model allowance this bound relies on must still be documented"


def test_noema_review_uploads_sidecar_evidence_on_failure() -> None:
"""A failed verdict phase ships the sanitized sidecar stderr and preflight report.

Before this step a failed Noema run left ``artifacts=0`` (run 33981136873:
3122 s, then HTTP 502, no per-route trace in the job log). The stderr file
is the sidecar sanitizer's bounded allowlist output -- the same file Strix
already publishes in ``strix-reports`` -- so shipping it on failure adds
diagnosis without adding exposure (#1935 follow-up).
def test_noema_review_retains_sanitized_sidecar_evidence_after_any_outcome() -> None:
"""Retain existing sanitized evidence on success, failure and cancellation.

A forced runner shutdown can still prevent upload; this contract only
removes the failure-only gate without adding raw logs or new files.
"""
workflow = workflow_text("noema-review.yml")
name = "Upload contextual-orchestrator sidecar evidence on failure"
name = "Upload contextual-orchestrator sidecar evidence"
step = workflow_step(workflow, name)
assert "if: failure() && env.PR_NUMBER != ''" in step
assert "if: always() && env.PR_NUMBER != ''" in step
strix_pin = re.search(
r"actions/upload-artifact@([0-9a-f]{40})", workflow_text("strix.yml")
).group(1)
Expand Down
Loading