Skip to content

ci: add non-required real-binary chain gate (W6.2) - #475

Merged
bbingz merged 9 commits into
mainfrom
ci/real-binary-gate-20261018
Oct 18, 2026
Merged

bbingz merged 9 commits into
mainfrom
ci/real-binary-gate-20261018

Conversation

@bbingz

@bbingz bbingz commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the W6.2 gap in docs/TODO.md: the real-binary chain tests in CollectorBinaryShadowIntegrationTests.swift (and the collector-only CollectorCLIIntegrationTests.swift) skipped everywhere because no CI workflow set the binary-path environment variables.

  • .github/workflows/real-binary.yml: new non-required workflow (weekly schedule, workflow_dispatch, and pull requests that touch the gate or the two test files). It is not part of the CI Gate contract and branch protection is unchanged.
  • scripts/ci/run-real-binary-gate.sh: builds Debug EngramCollector, EngramService, EngramRemoteServer, runs the three -only-testing classes with the env vars set, exports tests.json, and writes receipt.json / receipt.md (git sha, dirty paths, Xcode version, binary sha256s, per-test results). Usable locally for a documented receipt.
  • scripts/ci/check-real-binary-results.py: fails unless the exact expected test set executed; any skip other than the browser demo (needs ENGRAM_SHADOW_*, intentionally never set) or any failure fails the gate. A green exit with 50 skips is a fail.
  • tests/scripts/real-binary-gate.test.ts, tests/scripts/ci-workflow.test.ts: pin the verifier semantics, the workflow shape, the action pins, and the ENGRAM_SHADOW_* ban.
  • docs/TODO.md: W6.2 bullet updated.

This PR's own run of the new workflow is the proof that it works on hosted macos-15.

Evidence

CHECKS_RUN (implementer and an independent verifier, both on efb43b10):

  • Local full gate run: REAL_BINARY_GATE result=pass expected=50 passed=49 skipped=1 failed=0 (only the browser demo skipped), exit 0.
  • Negative proof: same test run without the env vars gives xcodebuild rc 0 with 50 skips; the verifier returns rc 1 result=fail expected=50 passed=0 skipped=50.
  • npx vitest run tests/scripts/real-binary-gate.test.ts tests/scripts/ci-workflow.test.ts tests/scripts/perf-result-gate.test.ts: 57 passed. npm test: 140 files, 2065 passed, 49 pre-existing skips. npm run lint, npm run typecheck:test: pass.
  • actionlint 1.7.12 (the version test.yml pins): pass. bash -n, py_compile: pass.
  • Gate scripts (check-xcodeproj-drift, check-app-mcp-cli-direct-writes, check-swift-conventions, check-swift-module-boundaries, check-invariants-ledger, check-plists): pass.

CHECKS_NOT_RUN:

  • Hosted macos-15 run: needs this PR (watch the Real-binary chain check on this PR).

Known limits

  • The verifier's first full run on a busy Mac saw 2 timing failures (expected=50 passed=47 failed=2); both passed on isolated re-run. The 25 s scope deadlines inside the Swift tests are unchanged here; if the hosted run is flaky, that is the next thing to look at, not the gate.
  • On pull_request events the receipt's git_sha is the synthetic merge commit.

Plan reference: docs/superpowers/plans/2026-09-05-collector-server-web.md W6 item 2.

https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v

reviewer added 3 commits October 18, 2026 07:52
Add .github/workflows/real-binary.yml (weekly, workflow_dispatch, and
pull requests that touch the gate's own files) plus
scripts/ci/run-real-binary-gate.sh, which builds the Debug
EngramCollector, EngramService and EngramRemoteServer tools, runs
CollectorBinaryShadowIntegrationTests, CollectorLargeHistoryBinaryTests
and CollectorCLIIntegrationTests with the explicit binary-path variables
and an isolated CFFIXED_USER_HOME, and exports the xcresult test tree.

scripts/ci/check-real-binary-results.py fails unless the exact expected
(class, test) set parsed from the Swift sources ran and passed; only the
opt-in browser demo may skip, so an all-skipped run is red. The workflow
is not part of test.yml or the ci-gate contract.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
tests/scripts/real-binary-gate.test.ts drives
check-real-binary-results.py with synthetic xcresult trees: it accepts
49 passed plus the opt-in browser skip (and 50 passed), and rejects an
all-skipped run (repro for TODO W6.2), a skip outside the allow list, a
failed test, a nonzero xcodebuild exit, missing/renamed/extra tests and
empty or malformed JSON.

ci-workflow.test.ts adds real-binary.yml to the YAML/SHA-pin/xcodegen
contracts and the self-hosted ban, and pins its policy header, triggers,
runner, timeout, concurrency and the runner script's -only-testing,
TEST_RUNNER_ binary variables and verifier call.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
Update the TODO W6.2 bullet with what shipped (real-binary.yml, the
runner script and the exact-set verifier), the local Debug receipt
(REAL_BINARY_GATE result=pass expected=50 passed=49 skipped=1 failed=0
at b2e8ef2, plus the all-skipped negative run rejected by the
verifier) and what remains: the PR's own hosted macos-15 run.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T01:01:04.085247Z efb43b1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

The first hosted run of the gate (PR #475, run 39084776142) executed all 50
tests: 48 passed, the browser demo skipped by design, and
CollectorLargeHistoryBinaryTests failed with BinaryShadowFailure.deadline
after both replicas had already stored the 114 MB history. macos-15 hosted
runners are several times slower than the Mac that produced the local
receipt, so the fixed 240 s scope budget is a host-speed limit, not a
correctness signal.

Add ENGRAM_REAL_BINARY_TIMEOUT_SCALE (1-10, default 1) read by
BinaryShadowScope, a --timeout-scale option on run-real-binary-gate.sh that
sets it for the test runner, and --timeout-scale 3 in real-binary.yml. The
scale lengthens deadlines only; assertions and the expected test set are
unchanged, and the ENGRAM_SHADOW_ opt-in stays unset.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
@bbingz

bbingz commented Oct 18, 2026

Copy link
Copy Markdown
Owner Author

Hosted result of the first run (39084776142): the gate executed the real chain, REAL_BINARY_GATE result=fail expected=50 passed=48 skipped=1 failed=1. The one failure was CollectorLargeHistoryBinaryTests hitting its fixed 240 s scope deadline after both replicas had stored the 114 MB history; the same test passes locally in the 265 s full run. Pushed a follow-up commit that adds --timeout-scale (deadline multiplier only, 1-10) and uses 3 on hosted runners; this PR's next Real-binary chain run is the proof.

bbingz and others added 5 commits October 18, 2026 10:20
Second hosted run (39089748788, timeout_scale=3): the large-history test got
past the hq replica's 114 MB byte check, then the m1 manifest fetch hit the
fixture's fixed 0.5 s request timeout (NSURLError -1001) while the runner was
still busy. Apply ENGRAM_REAL_BINARY_TIMEOUT_SCALE to the fixture's replica
fetch (0.5 s / 1.5 s) and chunk download (10 s) URLSession timeouts as well.
The Web read client's IPC timeout stays at its 2 s maximum; those calls
already retry until the scope deadline.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
…dget

Run 39093667839 passed with the large-history test at 429.6 s; run
39097383289 on the same code hit the scaled 720 s deadline while HQ was
still ingesting the 114 MB history (both replicas had the bytes after 12 s
in both runs). The hosted runner's speed varies about 2x between runs, so
use --timeout-scale 6 and raise the job timeout to 60 minutes. Assertions
and the expected test set are unchanged.

Claude-Session: https://claude.ai/code/session_01RE2f7JXQBa8xzoFrxuHS6v
@bbingz

bbingz commented Oct 18, 2026

Copy link
Copy Markdown
Owner Author

Hosted runs so far: #1 deadline at the fixed 240 s (both replicas had the bytes), #2 fixture 0.5 s replica request timeout, #3 pass (result=pass expected=50 passed=49 skipped=1, large-history 429.6 s), #4 deadline at 3x (720 s) with HQ still ingesting the 114 MB history after 12 min, replicas done in 12 s both times. The runner's speed varies about 2x run to run, so the latest commit uses --timeout-scale 6 and a 60 min job budget; assertions and the expected set are unchanged. If the gate still proves noisy, the next lever is building the three binaries Release instead of Debug for the hosted run.

@bbingz
bbingz merged commit 5b5b09a into main Oct 18, 2026
17 checks passed
@bbingz
bbingz deleted the ci/real-binary-gate-20261018 branch October 18, 2026 05:41
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