Skip to content

Stabilize parity downloads and retain deterministic failure evidence - #1104

Merged
rmcdaniel merged 9 commits into
mainfrom
ci/parity-cli-once
Nov 8, 2026
Merged

rmcdaniel merged 9 commits into
mainfrom
ci/parity-cli-once

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 8, 2026 •

Copy link
Copy Markdown
Member

The parity CI train repeatedly lost GitHub release-asset and Composer downloads, and a timer test could race its scheduler. Fetch the pinned CLI once per run with bounded HTTPS retries and a digest-checked official API fallback; share its artifact with every corpus consumer. Match Composer 2.10 transient errors within the existing locked-install retry policy, and hold the specific debug test timer until its deliberately due sweep has been observed.

A subsequent merge-group invocation failed in the frozen PHP reference recorder before Native comparison: the large-command-batches poll returned no task, but its final response was not retained. Keep that assertion and capture bounded HTTP/refusal facts and poll-specific retries on failure, without payloads or headers. This diagnostic is not a claimed fix or acceptance for the earlier reference failure.

Validation and limits:

  • The last source head b14296f passed 62 checks with one intended skip. Its ordinary queue entry failed; see 6722556394. Main remains M, and the PR is draft for the diagnostic successor.
  • The CLI transport, Composer retry controls and all six backend tests passed on earlier exact heads. The repaired timer case and separate fired-deadline refusal ran successfully; no count or refusal assertion was weakened.
  • The diagnostic files linted with PHP 8.4.27; two valid claims and five refusal shapes passed isolated functional checks. The four new diagnostic tests are explicitly wired into PHPUnit Feature in the latest successor. The earlier 7697b46 green train did not execute that class; this gap and the unchanged Composer confinement re-review are disclosed in the selection.
  • API fallback availability remains unproved. Earlier source attempts 1–5 and the queue failure retain their NONPASS attribution. This PR does not change the 3.3.0 cut M, tag or image, and does not include Reduce Native poll and completion database work #1099 or the frozen qualification-runner refresh.

Fixes #1103 and #1105 after successful integration. General owns the remaining work while the Server agent is Off.

Every corpus job downloaded CLI 2.2.0 from github.com on its own, so a
short burst of release-asset 504s failed several jobs before any fixture
ran (two #1101 merge groups lost 5 and 4 jobs). The shared-input job that
every corpus job already needs now fetches it once with a longer retry,
checks it against the committed digest and shares it as a dedicated
artifact; each corpus job checks the same digest again before use.

Refs #1103.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SonarCloud githubactions:S6506 flagged the new single download: with
--location, curl would follow a redirect to any protocol. Allow only
HTTPS for the request and every redirect.

Refs #1103.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

#1104 source train: terminal NONPASS (one source finding, one infrastructure failure)

At 10:19:20Z, head f997b91c (tree 3a0e8834) on base M 2a15179f: 58 success, 3 failure, 1 neutral, 1 skipped. Everything ran on attempt 1, with no rerun or cancellation.

run conclusion note
Shared Server fixtures 42469278760 success all 7 corpus jobs passed, along with every other part
PHPUnit Feature 42469278725 success the intended Candidate cancellation and prepared-local skip
Public Boundary 42469278736 / push 42469262951 success
SonarQube 42469278763 failure quality gate failed (ERROR QUALITY GATE STATUS: FAILED)
SonarCloud Code Analysis failure same gate: C Security Rating on New Code
CodeQL 42469277218 Analyze (rust) failure Initialize CodeQL: "Unable to download and extract CodeQL CLI: Unexpected HTTP response: 504" (09:57:51Z), the same github.com release-asset outage
CodeQL (default-setup notice) neutral "1 configuration not found" for /language:rust

The new fetch, observed. In published-sdk-adapters, the single invocation started at 09:57:15.63Z. parity-cli/dw.phar: OK came at 09:57:26.80Z, with no retry warnings in the step log. Every corpus consumer then passed its own digest check and ran.

Source finding (mine). SonarCloud reports one new-code vulnerability: githubactions:S6506 at server-parity.yml:282, "Not enforcing HTTPS here might allow for redirections to insecure websites". It flags the producer's curl --location. The older per-job curls had the same shape but were not new code.

Prepared successor (local only, not pushed).

  • Commit 2c22dc9165818493fe2024e8c9538a6f2d4eb91d, tree 3c09e8471438e77f44928638d7220f77354abf06, parent f997b91c.
  • One line: curl --fail --proto '=https' --proto-redir '=https' --location …, allowing HTTPS only for the request and every redirect.
  • Delta from f997b91c: 889 B / 67a562fb6e6c34635c018a478823831a4c3e5626e662ca237729b39f960b2945.
  • Full delta from M: 6,198 B / 2337cb2372d4c3c09bd087328f003593adc4ddd62aa73ce5c63eda4d9afd9352.

Next / owner: General decides on one successor push of 2c22dc91, leased on f997b91c. No rerun of the CodeQL infrastructure failure was selected.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Source review PASS for the HTTPS-only successor. One successor push and one fresh normal PR train are selected; owner Server.

Subject: 2c22dc9165818493fe2024e8c9538a6f2d4eb91d, sole parent f997b91c41683478e8d1b5d702fa5e37d03ae601, tree 3c09e8471438e77f44928638d7220f77354abf06. The 889 B successor diff has SHA-256 67a562fb6e6c34635c018a478823831a4c3e5626e662ca237729b39f960b2945. Full delta from M is 6,198 B / 2337cb2372d4c3c09bd087328f003593adc4ddd62aa73ce5c63eda4d9afd9352.

I read the complete successor, independently reproduced its tree and full diff, and ran the 11 Parts/AdapterCache tests: all passed. The only source change adds --proto '=https' --proto-redir '=https' to the shared CLI fetch. The committed PHAR checksum, producer/consumer verification, coverage and remaining workflow are unchanged. This restricts both the initial URL and redirects to HTTPS.

The first attempt remains NONPASS: the Sonar finding is a source issue; the CodeQL bundle HTTP 504 is infrastructure. All seven corpus jobs passed on that attempt, which establishes that the new artifact path ran; it does not make the failed train acceptable.

Before pushing, re-read this raw body and verify exact subject/parent/tree/diffs, clean worktree, unchanged main M, PR and remote old head f997b91, and secret scan. If they match, push this successor once to the existing draft #1104 with the exact old-head lease. Let its normal workflows run to terminal; report the actual head, checks, Sonar and CodeQL results, plus CLI fetch and consumer evidence. Preserve attempt 1 and its classification. No manual rerun, cancellation, further successor, ready/queue entry or local daemon effect is selected.

E4/1101 remains unchanged and out of the queue. #1099 remains deferred. The 3.3.0 tag and published image stay bound to M.

@rmcdaniel

Copy link
Copy Markdown
Member Author

#1104 second train (head 2c22dc91): terminal NONPASS on infrastructure; the source findings are cleared

At 10:47:15Z, head 2c22dc9165818493fe2024e8c9538a6f2d4eb91d (tree 3c09e847), everything on attempt 1, with no rerun or cancellation.

run conclusion
SonarQube 42471709158 success
SonarCloud Code Analysis Quality Gate passed; 0 open issues (S6506 cleared)
CodeQL 42471705533 success: no new alerts; Analyze (rust) and Analyze (actions) both succeeded
PHPUnit Feature 42471709079 success (the intended prepared-local skip)
Public Boundary 42471709131 / push 42471705052 success
Shared Server fixtures 42471709145 failure: published-sdk-adapters failed, so all corpus jobs were skipped and the result job failed

Cause. The single fetch got HTTP 504 on all 6 attempts:

  • the first came back at 10:31:27.9Z, about 11 s into the request;
  • the rest followed at 5 s intervals until 10:31:52.96Z, then exit 22.

Failed-job log: 16,414 B.

Classification. Infrastructure: the same github.com release-asset outage as both #1101 merge groups and attempt 1's CodeQL bundle. It is not caused by --proto. The HTTPS restriction had no effect on the 504s, which came from the first request.

Design observation (mine). The retry window was about 36 s, far below the 180 s budget, because the fixed --retry-delay 5 × 5 retries ends early. A fixed short backoff cannot ride out a multi-minute outage. Centralizing the fetch also means one failure now skips every corpus job. The aggregate result already required all of them, so the run's pass condition is unchanged.

Narrow options for a successor (not prepared, not pushed; each needs a selection):

  • (a) Exponential backoff that actually spans the budget: drop the fixed --retry-delay, use --retry 8 --retry-max-time 300. curl's default doubling (1, 2, 4 … 64 s) covers about 4 minutes.
  • (b) A second HTTPS source for the same digest-verified bytes: the release-asset API endpoint (api.github.com/repos/durable-workflow/cli/releases/assets/{id}, Accept: application/octet-stream), tried only after (a) is exhausted. Trust is unchanged, because the committed phar_sha256 is still required.
  • (c) Both.

Next / owner: General decides on a successor or any other action. No rerun was selected. E4/#1101 are unchanged; #1099 stays deferred.

The single parity CLI fetch hit 504s from the release download URL for
its whole 36 s retry window (#1104 attempt 2). It now lives in
scripts/ci/fetch-parity-cli.sh: HTTPS-only transfers with 10 s connect
and 60 s per-attempt bounds, doubling backoff inside a 240 s window
(300 s cap) on the release URL, and only if that transfer fails, the
same asset (2.2.0, id 614926795, 626,966 B) through its API URL with a
120 s window (180 s cap). Any completed transfer must match the
committed size and SHA-256; a mismatch fails at once, with no fallback.
ServerParityCliFetchTest drives every branch with recording fakes.

Refs #1103.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Option (c) source packet: bounded release URL, then the API URL only on transfer failure (SOURCE ONLY; not pushed, not run)

Identity.

  • Local ci/parity-cli-once: commit f2b02690ddbb5878f97822a1124357bbe233d71d, tree 3a0f6536458cc7188608bd0cdf6597b469210416, parent 2c22dc91 (the current Stabilize parity downloads and retain deterministic failure evidence #1104 head).
  • Delta from 2c22dc91: 11,905 B / b164a64e01214fa28a3ee24e6557fe7c041e0badb41c773be444937e4b048842.
  • Full delta from M: 16,187 B / 61f103ca3a80677a3566a3168a3a479a54f673f8db9b34abbff09da5d0610fe5. Three files, +225/−3:
    • .github/workflows/server-parity.yml (+42/−3);
    • new scripts/ci/fetch-parity-cli.sh: 2,179 B / 1e5e8109…, mode 0755;
    • new tests/Unit/ServerParityCliFetchTest.mjs: 6,859 B / 88e018ac….

Asset binding (read-only GitHub API, at 10:49Z):

  • Release 404473194, tag 2.2.0, not draft or prerelease.
  • Asset 614926795, dw.phar, 626,966 B, state: uploaded.
  • GitHub's own asset digest is sha256:fce532e6a49737aef9cb8a137fd66219928b2595764462be33b12a0fdf5abc7c, equal to the committed visibility.cli.phar_sha256.

Route evidence (read-only, unauthenticated HTTPS, no token):

  • Release download URL at 10:50:36Z: 302 to release-assets.githubusercontent.com, then 200. 626,966 B, sha256 fce532e6…, equal to the committed hash.
  • API URL (/releases/assets/614926795, Accept: application/octet-stream) at 10:50:12Z and 10:50:59Z: HTTP 504 after about 11 s, both times. I could not verify that this route serves the committed bytes. Both attempt 2's release-URL 504s (10:31Z) and these API 504s look like the same asset backend failing on either front.
  • The fallback is therefore a second front for the same asset, not an independent mirror. Either way, the committed size and digest decide.

scripts/ci/fetch-parity-cli.sh SHA256 SIZE OUTPUT

  • Refuses (exit 2) unless the digest is 64 hex characters and the size is a positive integer.
  • Every transfer: curl --fail --silent --show-error --proto '=https' --proto-redir '=https' --location --connect-timeout 10 --max-time 60 --retry 8 --retry-all-errors --retry-max-time <window>. curl's default doubling backoff (1, 2, 4 … s) applies, with no fixed delay.
  • Release download URL: window 240 s, wrapped in timeout 300.
  • Only if that transfer fails (non-zero exit), log release download URL failed (exit N); trying the release-asset API URL, then fetch https://api.github.com/repos/durable-workflow/cli/releases/assets/614926795 with -H 'Accept: application/octet-stream': window 120 s, timeout 180.
  • Total fetch ceiling 480 s. The step also gets timeout-minutes: 9. The job (usually 3–3.5 min) keeps its 25 min budget.
  • Acceptance, after whichever transfer completed: stat -c %s must equal SIZE, then sha256sum -c against SHA256. A completed transfer with other bytes fails at once, with no fallback. The transport used is logged, either release download URL or release-asset API URL.
  • The output file is removed before each transfer, so no partial file can survive.

Workflow

  • The producer step becomes bash scripts/ci/fetch-parity-cli.sh "$(jq -r '.visibility.cli.phar_sha256' tests/Fixtures/ServerParity/visibility-current-runs.json)" 626966 parity-cli/dw.phar, with timeout-minutes: 9. The upload, the artifact and all three consumers are unchanged, so consumer digest evidence (cli-artifact.txt) is identical.
  • Producer evidence keeps the parity-cli/dw.phar: OK line and adds the transport line.
  • The new test joins the existing comparator unit-test list in execution-and-codec, beside ServerParityImagePullTest, in the same network-none node container.
  • The path filters already cover scripts/ci/** and tests/Unit/ServerParity*.mjs.

Branch controls (ServerParityCliFetchTest.mjs: hosted, inert, not run locally)

The test uses recording fake curl and timeout on PATH, with no network. It covers:

  1. Release URL ok → 1 transfer, no API header, bounds asserted (window 240), timeout 300, transport logged, OK.
  2. Release URL completes with same-size wrong bytes, or with short bytes → exit 1 after exactly one transfer, so no fallback.
  3. Release URL fails, then API ok → 2 transfers. The second is the API URL with Accept: application/octet-stream. Windows are 240/120 and timeouts 300/180. Fallback and transport are logged, and OK.
  4. Release fails, then the API returns wrong bytes, short bytes, or fails → exit 1 after exactly two transfers. "Both transports failed" appears in the both-fail case.
  5. Malformed digest or size → exit 2 with zero transfers.
  6. Workflow wiring: the step calls the script with the committed digest and 626966, has timeout-minutes: 9 and no inline curl, three consumer digest checks remain, and the scripts/ci/** filter is present.

Static checks only: bash -n, node --check and YAML parse all pass. No test or fetch script was executed here.

Unchanged: HTTPS-only transfers, the committed hash, the default GITHUB_TOKEN (no auth added, no token widening), every consumer and every required check. Attempt 2 stays infrastructure NONPASS. E4 and #1101 are unchanged; #1099 stays deferred.

Delta from 2c22dc9 (11,905 B / b164a64e)
diff --git a/.github/workflows/server-parity.yml b/.github/workflows/server-parity.yml
index 44d03cdd..36dd4cad 100644
--- a/.github/workflows/server-parity.yml
+++ b/.github/workflows/server-parity.yml
@@ -273,15 +273,15 @@ jobs:
             mirror.gcr.io/library/python@sha256:bf44cdfcb76cd3b41e879bc058fc37ec5872002ccfde7fcb765e218cde0cd79c \
             "$(baseline php-2.11.8)"
       # Every corpus job replays CLI 2.2.0. Fetch it once for the whole run,
-      # bound to its committed digest, instead of once per corpus job; each
-      # consumer verifies the same digest again before use.
+      # bound to its committed digest and size, instead of once per corpus
+      # job: the release download URL, then the release-asset API URL only if
+      # that transfer fails (#1103). Each consumer verifies the digest again.
       - name: Fetch the parity CLI once, bound to its committed digest
+        timeout-minutes: 9
         run: |
           set -euo pipefail
-          mkdir -p parity-cli
-          curl --fail --proto '=https' --proto-redir '=https' --location --retry 5 --retry-all-errors --retry-delay 5 --retry-max-time 180 \
-            --output parity-cli/dw.phar https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar
-          printf '%s  %s\n' "$(jq -r '.visibility.cli.phar_sha256' tests/Fixtures/ServerParity/visibility-current-runs.json)" parity-cli/dw.phar | sha256sum -c
+          bash scripts/ci/fetch-parity-cli.sh \
+            "$(jq -r '.visibility.cli.phar_sha256' tests/Fixtures/ServerParity/visibility-current-runs.json)" 626966 parity-cli/dw.phar
       - name: Share the verified parity CLI with the corpus jobs
         uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
         with:
@@ -2374,6 +2374,7 @@ jobs:
               tests/Unit/ServerParityUpdateValidationProcessTest.mjs \
               tests/Unit/ServerParityKilledAuthorPollTest.mjs \
               tests/Unit/ServerParityImagePullTest.mjs \
+              tests/Unit/ServerParityCliFetchTest.mjs \
               tests/Unit/ServerParityAdapterCacheTest.mjs \
               tests/Unit/ServerParityWorkerSessionsContractTest.mjs \
               tests/Unit/ServerParityWorkerSessionActivitiesContractTest.mjs \
diff --git a/scripts/ci/fetch-parity-cli.sh b/scripts/ci/fetch-parity-cli.sh
new file mode 100755
index 00000000..9630f018
--- /dev/null
+++ b/scripts/ci/fetch-parity-cli.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# Fetches CLI 2.2.0's dw.phar once for a Shared Server fixtures run (#1103).
+#
+# Usage: fetch-parity-cli.sh SHA256 SIZE OUTPUT
+#
+# The release download URL is tried first. Only if that transfer itself fails
+# is the same release asset fetched through its GitHub API URL. Either way the
+# file is accepted only with the exact size and the committed SHA-256: a
+# completed transfer with other bytes fails at once, with no second source.
+#
+# Every transfer is HTTPS-only, redirects included, with a 10 s connect and a
+# 60 s per-attempt bound. curl retries with its doubling backoff inside a
+# per-route window, and `timeout` caps each route (release URL 300 s, API URL
+# 180 s), so the whole fetch ends within 480 s.
+set -euo pipefail
+
+want="${1:-}"
+size="${2:-}"
+out="${3:-}"
+[[ "$want" =~ ^[0-9a-f]{64}$ && "$size" =~ ^[1-9][0-9]*$ && -n "$out" ]] || {
+    echo "fetch-parity-cli.sh: usage: fetch-parity-cli.sh SHA256 SIZE OUTPUT" >&2
+    exit 2
+}
+
+primary=https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar
+# Release 404473194 (tag 2.2.0), asset 614926795 "dw.phar", 626,966 bytes.
+asset=https://api.github.com/repos/durable-workflow/cli/releases/assets/614926795
+
+fetch() { # CEILING WINDOW URL [CURL OPTION...]
+    rm -f "$out"
+    timeout "$1" curl --fail --silent --show-error --proto '=https' --proto-redir '=https' --location \
+        --connect-timeout 10 --max-time 60 --retry 8 --retry-all-errors --retry-max-time "$2" \
+        --output "$out" "${@:4}" "$3"
+}
+
+mkdir -p "$(dirname "$out")"
+if fetch 300 240 "$primary"; then
+    echo "parity CLI transport: release download URL"
+else
+    status=$?
+    echo "parity CLI transport: release download URL failed (exit $status); trying the release-asset API URL" >&2
+    if ! fetch 180 120 "$asset" -H 'Accept: application/octet-stream'; then
+        echo "fetch-parity-cli.sh: both transports failed" >&2
+        exit 1
+    fi
+    echo "parity CLI transport: release-asset API URL"
+fi
+
+actual="$(stat -c %s "$out")"
+[[ "$actual" = "$size" ]] || {
+    echo "fetch-parity-cli.sh: $out is $actual bytes, expected $size" >&2
+    exit 1
+}
+printf '%s  %s\n' "$want" "$out" | sha256sum -c
diff --git a/tests/Unit/ServerParityCliFetchTest.mjs b/tests/Unit/ServerParityCliFetchTest.mjs
new file mode 100644
index 00000000..801e0668
--- /dev/null
+++ b/tests/Unit/ServerParityCliFetchTest.mjs
@@ -0,0 +1,132 @@
+// The Shared Server fixtures producer fetches CLI 2.2.0's dw.phar once (#1103):
+// the release download URL first, then the release-asset API URL only when
+// that transfer fails; any completed transfer must match the committed size
+// and SHA-256, with no second source after a mismatch. curl and timeout are
+// replaced by recording fakes, so no network is used.
+import test from 'node:test';
+import assert from 'node:assert/strict';
+import {createHash} from 'node:crypto';
+import {chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs';
+import {tmpdir} from 'node:os';
+import {join, resolve} from 'node:path';
+import {spawnSync} from 'node:child_process';
+
+const script = resolve('scripts/ci/fetch-parity-cli.sh');
+const workflow = readFileSync(resolve('.github/workflows/server-parity.yml'), 'utf8');
+const PRIMARY = 'https://github.com/durable-workflow/cli/releases/download/2.2.0/dw.phar';
+const API = 'https://api.github.com/repos/durable-workflow/cli/releases/assets/614926795';
+const GOOD = 'genuine parity CLI bytes\n';
+const SAME_SIZE_WRONG = 'Genuine parity CLI bytes\n';
+const SHA = createHash('sha256').update(GOOD).digest('hex');
+
+// FAKE_PRIMARY / FAKE_API: ok | wrong | short | fail. Each call is one log line.
+const fakeCurl = `#!/usr/bin/env bash
+printf '%s\\x1f' "$@" >> "$CALL_LOG"; printf '\\n' >> "$CALL_LOG"
+out=""; url=""
+while (($#)); do case "$1" in --output) out="$2"; shift 2 ;; https://*) url="$1"; shift ;; *) shift ;; esac; done
+case "$url" in ${PRIMARY}) mode="$FAKE_PRIMARY" ;; ${API}) mode="$FAKE_API" ;; *) exit 3 ;; esac
+case "$mode" in
+  ok) printf '%s' "$GOOD" > "$out" ;;
+  wrong) printf '%s' "$SAME_SIZE_WRONG" > "$out" ;;
+  short) printf 'x' > "$out" ;;
+  *) echo "curl: (22) The requested URL returned error: 504" >&2; exit 22 ;;
+esac
+`;
+const fakeTimeout = `#!/usr/bin/env bash
+echo "$1" >> "$TIMEOUT_LOG"; shift; exec "$@"
+`;
+
+function run(t, primary, api, args = [SHA, String(GOOD.length)]) {
+  const dir = mkdtempSync(join(tmpdir(), 'fetch-parity-cli-'));
+  t.after(() => rmSync(dir, {recursive: true, force: true}));
+  for (const [name, body] of [['curl', fakeCurl], ['timeout', fakeTimeout]]) {
+    writeFileSync(join(dir, name), body);
+    chmodSync(join(dir, name), 0o755);
+  }
+  writeFileSync(join(dir, 'calls'), '');
+  writeFileSync(join(dir, 'timeouts'), '');
+  const out = join(dir, 'parity-cli', 'dw.phar');
+  const result = spawnSync('bash', [script, ...args, out], {
+    encoding: 'utf8', timeout: 10000,
+    env: {...process.env, PATH: `${dir}:${process.env.PATH}`, CALL_LOG: join(dir, 'calls'), TIMEOUT_LOG: join(dir, 'timeouts'),
+      FAKE_PRIMARY: primary, FAKE_API: api, GOOD, SAME_SIZE_WRONG},
+  });
+  const calls = readFileSync(join(dir, 'calls'), 'utf8').split('\n').filter(Boolean)
+    .map(line => line.split('\x1f').filter(Boolean));
+  const timeouts = readFileSync(join(dir, 'timeouts'), 'utf8').trim().split('\n').filter(Boolean);
+  return {...result, calls, timeouts, out};
+}
+
+function assertBounded(call, window) {
+  for (const flag of ['--fail', '--location', '--retry-all-errors']) assert.ok(call.includes(flag), flag);
+  for (const [flag, value] of [['--proto', '=https'], ['--proto-redir', '=https'], ['--connect-timeout', '10'],
+    ['--max-time', '60'], ['--retry', '8'], ['--retry-max-time', window]]) {
+    assert.equal(call[call.indexOf(flag) + 1], value, flag);
+  }
+}
+
+test('the release download URL alone is used when it yields the committed bytes', t => {
+  const result = run(t, 'ok', 'ok');
+  assert.equal(result.status, 0, result.stderr);
+  assert.equal(result.calls.length, 1);
+  assert.equal(result.calls[0].at(-1), PRIMARY);
+  assert.ok(!result.calls[0].includes('-H'), 'no API header on the release URL');
+  assertBounded(result.calls[0], '240');
+  assert.deepEqual(result.timeouts, ['300']);
+  assert.match(result.stdout, /parity CLI transport: release download URL\n/);
+  assert.match(result.stdout, /dw\.phar: OK\n/);
+  assert.equal(readFileSync(result.out, 'utf8'), GOOD);
+});
+
+test('a completed transfer with other bytes fails at once and never falls back', t => {
+  for (const mode of ['wrong', 'short']) {
+    const result = run(t, mode, 'ok');
+    assert.equal(result.status, 1, mode);
+    assert.equal(result.calls.length, 1, `${mode}: no second source`);
+    assert.equal(result.calls[0].at(-1), PRIMARY);
+  }
+});
+
+test('only a failed release download falls back to the release-asset API URL', t => {
+  const result = run(t, 'fail', 'ok');
+  assert.equal(result.status, 0, result.stderr);
+  assert.equal(result.calls.length, 2);
+  assert.equal(result.calls[1].at(-1), API);
+  assert.equal(result.calls[1][result.calls[1].indexOf('-H') + 1], 'Accept: application/octet-stream');
+  assertBounded(result.calls[0], '240');
+  assertBounded(result.calls[1], '120');
+  assert.deepEqual(result.timeouts, ['300', '180']);
+  assert.match(result.stderr, /release download URL failed \(exit 22\); trying the release-asset API URL/);
+  assert.match(result.stdout, /parity CLI transport: release-asset API URL\n/);
+  assert.match(result.stdout, /dw\.phar: OK\n/);
+});
+
+test('the API URL is held to the same size and digest, and both failing fails the step', t => {
+  for (const [api, expected] of [['wrong', 1], ['short', 1], ['fail', 1]]) {
+    const result = run(t, 'fail', api);
+    assert.equal(result.status, expected, api);
+    assert.equal(result.calls.length, 2, `${api}: exactly two transfers`);
+  }
+  assert.match(run(t, 'fail', 'fail').stderr, /both transports failed/);
+});
+
+test('a malformed digest or size is refused before any transfer', t => {
+  for (const args of [['', '25'], ['abc', '25'], [SHA, '0'], [SHA, 'x']]) {
+    const result = run(t, 'ok', 'ok', args);
+    assert.equal(result.status, 2, JSON.stringify(args));
+    assert.deepEqual(result.calls, []);
+  }
+});
+
+test('the producer step runs the fetch with the committed digest and the bound asset size', () => {
+  const producer = workflow.slice(workflow.indexOf('      - name: Fetch the parity CLI once, bound to its committed digest\n'));
+  const step = producer.slice(0, producer.indexOf('\n      - ', 1));
+  assert.match(step, /\n {8}timeout-minutes: 9\n/);
+  assert.ok(step.includes(`bash scripts/ci/fetch-parity-cli.sh \\
+            "$(jq -r '.visibility.cli.phar_sha256' tests/Fixtures/ServerParity/visibility-current-runs.json)" 626966 parity-cli/dw.phar`));
+  assert.doesNotMatch(step, /curl /, 'every transfer goes through the script');
+  // Each corpus job still checks the shared file against the committed digest before use.
+  const consumer = "printf '%s  %s\\n' \"$(jq -r '.visibility.cli.phar_sha256' tests/Fixtures/ServerParity/visibility-current-runs.json)\" parity-consumers/dw.phar | sha256sum -c > parity-evidence/cli-artifact.txt";
+  assert.equal(workflow.split(consumer).length - 1, 3);
+  assert.match(workflow, /\n {6}- scripts\/ci\/\*\*\n/);
+});

@rmcdaniel

Copy link
Copy Markdown
Member Author

Source and inert-control review PASS for option (c). One successor push and one fresh normal #1104 train are selected, owned by Server.

Subject f2b02690ddbb5878f97822a1124357bbe233d71d, parent 2c22dc9165818493fe2024e8c9538a6f2d4eb91d, tree 3a0f6536458cc7188608bd0cdf6597b469210416. Successor: 11,905 B / b164a64e01214fa28a3ee24e6557fe7c041e0badb41c773be444937e4b048842; full delta from M: three files, 16,187 B / 61f103ca3a80677a3566a3168a3a479a54f673f8db9b34abbff09da5d0610fe5.

I read all three file changes, independently reproduced the tree and diffs, and ran the six new fetch controls plus the 11 Parts/AdapterCache tests inside a network/socket-isolated bwrap environment: 17/17 passed, with 15/15 isolation probes, no tripwire call and empty outer stderr. Final TAP SHA-256 is 8a639a41068f4b4a12faa5af2bfa9c248e18369d9eeaffdfc9ae156358cb9538. Earlier local sandbox setup failures are retained separately: explicit user-namespace setup and Node mapping/PATH were corrected before the successful run; they do not represent candidate test passes. No real curl or Docker call ran in these controls.

The primary route and every redirect stay HTTPS-only. The API route is used only after a failed transfer; a completed transfer with wrong size/hash fails immediately with no fallback. Both transports have connect/per-attempt and retry/route limits; the step timeout is nine minutes. The expected size is 626,966, and the committed checksum remains decisive at producer and consumers. I independently re-read release 404473194/tag 2.2.0 and asset 614926795: name, size and GitHub digest match the committed digest. GitHub documents anonymous public binary downloads with Accept: application/octet-stream and 200/302 handling.

Limit: the API route's actual bytes were not observed successfully; the owner's two read-only attempts got 504. It may share the same backend outage. Inert controls establish branch/verification behavior, not transport availability. Do not claim an independently available mirror or guaranteed recovery. Attempt 1 remains source/infrastructure NONPASS and attempt 2 remains infrastructure NONPASS.

Re-read this raw body and verify exact head/parent/tree/diffs, clean worktree, actual main/merge-base M, remote/PR old head 2c22dc9, secret scan and terminal attempt-2 state. If exact, push once to the existing draft with the old-head lease. Run one fresh normal train and return terminal Sonar/CodeQL/corpus checks, the actual route and digest receipts, and skipped coverage. Do not rerun old jobs, cancel, prepare another successor, mark ready or queue without a separate decision. No local daemon effect is selected. E4/1101 stays unchanged and out of the queue; #1099 stays deferred and the published 3.3.0 tuple remains M/D.

@rmcdaniel

Copy link
Copy Markdown
Member Author

#1104 third train (head f2b02690, option (c)): terminal NONPASS — the fix ran and passed; the failures are a GitHub API outage and one Native test race

At 11:31:50Z: 57 success, 5 failure, 1 skipped. Everything ran on attempt 1, with no rerun or cancellation.

The CLI fix itself, observed.

  • Producer (published-sdk-adapters, run 42474309384): parity CLI transport: release download URL at 11:08:16.698Z, then parity-cli/dw.phar: OK at 11:08:16.704Z, less than 1 s after the step started at 11:08:15.83Z. The API fallback was not used, so its route stays availability-unproven.
  • All 7 corpus jobs succeeded: execution-and-codec corpus and corpus-b; postgres-storage corpus ×2; mysql-execution corpus ×3. Each consumer fetched parity-cli-2.2.0 with digest-mismatch: error and passed its committed-digest check.
  • The new branch controls ran in hosted CI. The corpus-b comparator evidence reports # tests 2949 / # pass 2949 / # fail 0, against 2943 / 2943 / 0 on attempt 1 at f997b91c. The delta of 6 is exactly the six ServerParityCliFetchTest cases.
    • Limit: comparator-tests.txt keeps only its last 65,536 B, so the six test names themselves are not in the retained file. Their passing is inferred from the counts and the step's success.
  • Sonar: Quality Gate OK: reliability, security and maintainability ratings 1, 0.0 % duplication, 100 % hotspots reviewed. There are 3 new code smells, shell:S7679, "assign this positional parameter to a local variable", at fetch-parity-cli.sh:31–33 ("$1", "$2", "$3" inside fetch()). They are non-blocking and could be tidied in any later successor.
  • CodeQL: success, no new alerts; Analyze (rust) and Analyze (actions) both succeeded.

Failures.

check cause classification
PHPUnit Feature 42474309487: PHPUnit feature suite and Feature source qualification Composer dist downloads from api.github.com/repos/*/zipball/* timed out or died (curl 28/56, "tried 5 times", 11:09:57–11:11:30Z), and composer exited 100 infrastructure: a GitHub API outage, same family
postgres-storage (postgres-17, sdk-directions) same Composer api.github.com zipball failures (curl 56), composer exit 100 (11:15–11:16Z) infrastructure
mysql-execution (existing-php-mysql-matrix, native-tests-b) occurrence_deadlines::a_reopen_after_the_anchor_is_due_immediately_at_the_anchor panicked at tests/execution/occurrence_deadlines.rs:165: expected 200, got 409 condition_wait_occurrence_timed_out. The other 373 tests in the shard passed. Native test race in M's own suite (#1098); unrelated to #1104's files
Shared Server fixtures result aggregate of the two fixture failures above —

The Native race.

  • The test moves A into the past on the first wait's timer row, then immediately reopens (Duration::ZERO), assuming "the engine does not fire it first".
  • occurrence_anchor (wait_timeouts.rs:254–255) refuses with condition_wait_occurrence_timed_out whenever a chain timer already has fired_at. So any due-timer sweep keyed on the row's fire_at, that runs between the UPDATE and the reopen, makes the assertion fail.
  • It passed on M's merge group and on Qualify the runner against the published Native 3.3.0 index #1101 and Stabilize parity downloads and retain deterministic failure evidence #1104 attempt 1, so it is intermittent. It needs its own owning issue and a deterministic test fix, for example holding the timer sweep or asserting either outcome with the fired timer bound. I propose filing that, deduplicated, on selection.

Next / owner: General decides. Options include a fresh train when GitHub's API recovers, the Native test-race issue, and whether to tidy S7679. Nothing was rerun. Attempts 1–2 stay NONPASS. E4/#1101 are unchanged; #1099 stays deferred.

…nance loop

The anchored past-A reopen test moved the first wait's timer fire_at into
the past and then ran a wake turn. The maintenance loop fires any pending
timer whose fire_at has passed every 250 ms, so a tick inside the wake turn
fired that timer and the reopen was refused with
condition_wait_occurrence_timed_out (#1105).

Add a debug-build seam, runtime::timer_holds, beside poll_pauses: a test
holds one timer by ID and fire_due_timers leaves it pending, reporting the
first tick that found it due. The test now waits for that tick before the
wake turn, keeps the strict 200 at the past A, and checks that the first
timer ends cancelled and unfired. The fired-deadline refusal control is
unchanged. Release builds compile neither the seam nor its call site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Status: attempts 1, 2 and 3 all remain NONPASS. The third attempt's failures:

The #1105 fix is prepared locally as af59535 on top of f2b0269 and is not pushed.

Next action: General reviews it and selects a successor push. Then Server rewrites this PR's final scope/title (CLI fetch + #1105) and runs one CI invocation.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Source review PASS for the deterministic timer-test repair. One #1104 successor push and one fresh normal train are selected, owned by Server; no other PR or local execution.

Subject af5953504931c706079e7e8fb0e544a5e4158e2a, parent f2b02690ddbb5878f97822a1124357bbe233d71d, tree 41e2f09410c94abe451d902d038f08e42a030f31. The four-file successor is 5,953 B / 3df0ec4befa387d2c5bebabef6b7b6612beae4a9194384beee2ca239531c3387. Full delta from M is seven files, 22,140 B / e92a99581760bccb45d1076feb627d6ba26dc3c51da263bf65fe875156adb9fd.

I read the complete repair and independently reproduced the tree and full diff; diff check passed. The original test placed A in the past, making timer 1 eligible for the real 250 ms sweep before the wake completion. The repair registers a hold for that exact timer ID, forces and awaits a tick that observes it due and skips it, then keeps the strict 200 reopen assertion. It verifies timer 1 was cancelled unfired before normal future ticks can affect it; timer 2 remains unheld and must fire at the original A. The fired-timer refusal control is unchanged. No retry, tolerance or ignore substitutes for the behavior.

Scope/limit: this is a debug-build test seam, following the existing poll_pauses pattern, not a cfg(test)-only library item. It is inert unless an in-process caller holds a specific timer; default release builds omit the module and call site. The regression is likewise absent from cargo test --release. Current CI uses debug test builds, so require the named test to run and pass on its actual backend lanes. The new Rust code has not been compiled locally; first compile/execution will be this train. The earlier 17 isolated CLI/Parts/AdapterCache tests cover the unchanged fetch work, not this Rust repair.

Re-read this raw body and verify exact head/parent/tree/diffs, clean worktree, actual main and merge-base M, remote/PR old head f2b0269, terminal attempt-3 state and clean secret scan. If exact, push once with the old-head lease to the existing draft. Rewrite its title/description around the final CI-stability scope (verified shared CLI transport plus #1105's timer-test race), with these validation limits. Preserve all three NONPASSs; no optional S7679 cleanup.

Let one normal train finish. Report compilation/checks, all corpus fetch/digest routes, the named repaired test and separate fired-timer refusal per backend, and any skipped/truncated coverage. Keep Composer download failures classified separately; do not cancel, rerun, add another successor, mark ready or queue without a new decision. E4/1101 remains unchanged and out of the queue, #1099 deferred, and Native 3.3.0 tag/image remain bound to M/D.

@rmcdaniel rmcdaniel changed the title Fetch the verified parity CLI once per Shared Server fixtures run Stabilize Shared Server fixtures: verified shared parity CLI transport and a deterministic timer-test repair Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

Attempt 4 T0, under selection 6721138138 (re-read raw: 2,701 B / f0fc840e).

Guards (all exact before the push)

  • head af595350, parent f2b02690, tree 41e2f094;
  • successor diff 5,953 B / 3df0ec4b…;
  • full diff from M: 7 files, 22,140 B / e92a9958…;
  • git diff --check clean; worktree clean;
  • origin/main = merge-base = M 2a15179f;
  • remote and PR head were f2b02690; attempt 3 runs all completed;
  • secret scan clean.

Push: one push with an old-head lease at 11:52:53.778Z: f2b02690..af595350, a fast-forward. The remote now shows af595350.

Title and description rewritten for the final CI-stability scope (#1103 transport + #1105 timer race). They include the validation limits: debug-build seam, absent from --release, no local compile. All three NONPASSs are kept.

Train started 11:52:57–11:53:01Z:

Next, owned by Server: let this one train finish, then report:

  • compilation and checks;
  • corpus fetch/digest routes;
  • the repaired test and the fired-refusal control, by name, per backend;
  • any skipped or truncated coverage.

Composer failures will be classified separately. No cancel, rerun, successor, ready or queue.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Attempt 4 (af595350): terminal NONPASS, infrastructure. The #1105 repair was not exercised: every corpus job was skipped. Checks: 14 pass, 5 fail, 5 skipped. All on run attempt 1, finished 12:05:55Z. No cancel, rerun or successor.

Compile

  • native-debug-build passed: Compiling durable-workflow-server with the dev profile, Finished in 1m 38s. That compiles the library with debug_assertions, so the new runtime::timer_holds module and its fire_due_timers call site compiled. The log has no warning naming them.
  • codec-native-build passed. CodeQL Analyze (rust) passed. SonarCloud and SonarQube passed.
  • The test target was not compiled, because no job that runs cargo test --test execution started. So occurrence_deadlines.rs is still uncompiled.

CLI transport (#1103) — worked under a live outage

  • The published-sdk-adapters fetch step logged curl 56, 56 and 28 (60 s, 0 bytes) on release-URL attempts between 11:53:44Z and 11:54:48Z. curl's backoff then succeeded at 11:54:52.88Z: parity CLI transport: release download URL, then parity-cli/dw.phar: OK.
  • So the size and digest gate passed, and the API fallback was not needed (it remains unexercised).
  • The artifact upload step followed. No consumer jobs ran.

Failures, all Composer dist downloads from api.github.com zipball (curl 28/56)

  • published-sdk-adapters (job 128722561838): Build the separate corrected cohort with the existing SDK cache exited 100. The run's failed-sdk-setup-diagnostics artifact, file corrected-marker-adapters/php-range-install.txt, shows curl 56 on psr/http-message, psr/http-factory, symfony/polyfill-php80/82, guzzlehttp/psr7, psr/log, durable-workflow/sdk and others. Because this job failed, mysql-execution, postgres-storage, execution-and-codec and codec-deadline-health were skipped, and Shared Server fixtures result failed.
  • Repository contracts (job 128722534340): Install worker OpenAPI validation dependencies exited 100 (symfony/yaml, doctrine/lexer, doctrine/inflector, dragonmantank/cron-expression). This check failed for the first time on Stabilize parity downloads and retain deterministic failure evidence #1104. Its node contract tests before that step passed.
  • PHPUnit feature suite (job 128722604091): the same zipball failures (phpoption, polyfill-mbstring, symfony/yaml, aws-crt-php, …).
  • Feature source qualification: the aggregate, failing because PREFLIGHT_RESULT and FEATURE_RESULT were both failure. Candidate cancellation… was skipped.

Not obtained (owed by a later train)

  • occurrence_deadlines::a_reopen_after_the_anchor_is_due_immediately_at_the_anchor and occurrence_deadlines::a_wake_turn_finishing_after_its_fired_deadline_is_refused: no backend lane ran either.
  • Corpus consumer fetch and digest routes.

Record: attempts 1–4 are all NONPASS. Attempt 4 is pure infrastructure, and none of its failures touches this PR's changes.

Next, owned by General: decide on a fresh train once api.github.com zipball downloads recover. Server will not rerun, cancel, push, mark ready or queue without a selection. E4/#1101 unchanged, #1099 deferred, the 3.3.0 tag and image stay at M/D.

@rmcdaniel

Copy link
Copy Markdown
Member Author

General disposition after attempt 4: hold a fresh train; no queue or bypass. Actual PR head remains af5953504931c706079e7e8fb0e544a5e4158e2a, draft, with main still M. Independent check read: 14 success, 5 failure, 5 skipped, all terminal. The owner record is consistent with that inventory.

The debug library build compiled the new module and call site. The execution test target, repaired past-anchor test, fired-deadline refusal control and corpus consumers remain unqualified because those lanes did not start. Attempts 1–4 remain NONPASS. The CLI's primary route succeeded after transient errors; the API fallback remains availability-unproven.

Three anonymous GETs for pinned psr/container, psr/http-message and symfony/yaml zipballs at 12:16:27–32 UTC each hit the 5 s connection timeout, with 0 response bytes and no HTTP status. This host observation does not establish a global GitHub outage or hosted-runner behavior, but provides no recovery evidence for selecting another train now. Nothing was extracted or executed. Private result SHA256 6cc94a99863ea5f1dc354f56da28098065735768edcb1caabae245a47e9ab492.

Next, Server owns a source-only inspection of the current Composer cache/retry arrangement and the smallest practical recovery proposal. No new push, rerun, ready/queue action or local execution is selected. General will review that proposal and fresh availability evidence. Runner #1101 and #1099 remain unchanged and deferred; the 3.3.0 cut and image remain M/D.

@rmcdaniel

rmcdaniel commented Nov 8, 2026 •

Copy link
Copy Markdown
Member Author

Composer download recovery: source-only proposal (Server)

Read-only. Nothing is pushed, run or rerun. The source is M 2a15179f; the evidence is attempt 3 (run 42474309384) and attempt 4 (runs 42477677211 and 42477677177).

What failed, and why there was no retry

Every Composer failure in attempts 3 and 4 is a curl transport error from api.github.com/repos/*/zipball/*, for example (verbatim, attempt-4 diagnostics corrected-marker-adapters/php-range-install.txt):

Failed to download psr/http-message from dist: curl error 56 while downloading https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71: Connection died, tried 5 times before giving up

There are three kinds of call site:

Call site Path Retry today
Shared Server fixtures: corrected-cohort php/php-range installs; sdk-composer-cache.sh warm (sdk-direction and range-repair profiles, e.g. attempt-3 postgres-17 sdk-directions); every --rm install in server-parity.yml scripts/ci/run-composer.sh Exists, but never fires for this failure.
PHPUnit Feature → Repository contracts, "Install worker OpenAPI validation dependencies" direct docker run composer:2.10.3@… none
PHPUnit Feature → feature suite (phpunit-feature.yml:398) composer update … --no-install then composer install in the app image, in the same container command that runs PHPUnit none

Defect in run-composer.sh (line 48 at M):

transient='could not be downloaded \((HTTP/[0-9.]+ (429|5[0-9][0-9])|curl error (6|7|28|35|52|56))'

Composer 2.10 uses the could not be downloaded (…) shape only for HTTP status errors (The "…" file could not be downloaded (HTTP/2 504 )). It reports transport failures as curl error N while downloading https://…. So the curl half of the pattern never matches.

  • Across the six failing logs and diagnostics read today, I count 0 transient download failure … retrying lines, and every install failed on its first attempt.
  • The existing tests (composer_trust_test.py:402–420, sdk_composer_cache_test.py:40) only use the HTTP shape, which is why the gap went unnoticed.
  • A secondary detail: the old curl alternative has no terminator, so curl error 6 would also prefix-match curl error 60. That is a TLS trust failure and must never be retried.

Proposal — Stage 1 (smallest; fixes the Shared Server fixtures path)

One file of logic plus tests. No lock, trust, image, sink or workflow change.

-# A locked install only downloads pinned dists, so it is safe to repeat. Retry
-# it, at most three attempts in all, only when Composer reports a transient
-# download failure such as GitHub codeload's HTTP 429 rate limit. ...
-transient='could not be downloaded \((HTTP/[0-9.]+ (429|5[0-9][0-9])|curl error (6|7|28|35|52|56))'
+# A locked install only downloads pinned dists, so it is safe to repeat. Retry
+# it, at most three attempts in all, only when Composer reports a transient
+# download failure: an HTTP 429/5xx (`could not be downloaded (HTTP/2 504 )`)
+# or a curl transport error (`curl error 56 while downloading https://…`).
+# TLS and every other curl error fail on the first attempt. ...
+transient='could not be downloaded \(HTTP/[0-9.]+ (429|5[0-9][0-9])[^0-9]|curl error (6|7|28|35|52|56) while downloading https://'

Correction (12:31Z): the first posting ended the HTTP alternative with \). That matches HTTP/2's (HTTP/2 504 ) but would have dropped HTTP/1.1's (HTTP/1.1 504 Gateway Timeout), which the current pattern matches. It now ends with [^0-9]. Add an HTTP/1.1 reason-phrase case to the tests.
Tests in composer_trust_test.py, using the existing retrying() harness:

  • the verbatim line above, failing twice → (0, 3); failing three times → Composer's own status after 3 runs;
  • curl error 60 while downloading https://…: SSL certificate problem → 1 run, no retry;
  • the curl line with update, and with a kept (--name) container → 1 run (the existing exclusions still hold);
  • the existing HTTP 429 cases unchanged.

Optional tuning (a separate question; I'd take it): the backoff is currently 20 s then 40 s, a 60 s window. Attempt 4's outage ran at least 11:53:44–11:57:19Z. Changing to sleep $((attempt == 1 ? 30 : 90)) gives a 120 s window, adding at most 60 s per failing install. The job's 25-minute bound still holds. No retry window can cover a sustained outage; this only rides out minute-scale ones.

Coverage: Stage 1 covers the published-sdk-adapters failure (attempt 4) and the sdk-directions failure (attempt 3), so it recovers Shared Server fixtures.

Stage 2 — PHPUnit Feature (not "smallest"; disclosed so expectations are right)

  • 2a, contracts. Route the OpenAPI install through bash scripts/ci/run-composer.sh --rm -v "$PWD:/app" -w /app -- install --no-dev --no-scripts --no-interaction --no-progress --prefer-dist --ignore-platform-reqs.
    • Same Composer base (brotli-safe-composer.sh builds on the same composer:2.10.3@sha256:da624c…), plus the Brotli floor and the stricter checked CA pair.
    • It touches the trust registry tests/Unit/Support/composer-sinks.json (sink line and count) and needs that review.
  • 2b, feature suite. The install shares one -lc command with PHPUnit itself, so a retry would rerun the tests. Fixing it properly means splitting dependency resolution into its own retryable --rm container that writes vendor to a mounted directory. That is a structural change, not proposed now.
  • Until then, a fresh train's PHPUnit Feature and Feature source qualification results stay exposed to api.github.com zipball outages even with Stage 1.

Not proposed

  • A persistent cross-run Composer dist cache. All 86 dists in the server composer.lock have an empty shasum, so Composer can't integrity-check restored zipballs. phpunit-feature.yml also says "source and vendors stay fresh". The verified job-scoped cache (sdk-composer-cache.sh, Reuse the claimed history total for the first history page #1093) stays the only Composer cache.
  • Blind whole-train reruns. Before selecting a fresh train, a cheap gate is GitHub's status for API requests / Git operations, or a run that shows zipball success, rather than another full train.

Carrier and next step (owner: General). Stage 1 fits #1104's CI-stability scope as one more successor, or a separate small PR; your call. Nothing is prepared or pushed until selected. E4/#1101 unchanged, #1099 deferred, the 3.3.0 tag and image stay at M/D.

Composer 2.10 reports curl transport failures as curl error N while
downloading https://..., while the wrapper only matched errors inside a
could-not-be-downloaded parenthesis. Match the actual format and preserve
HTTP 429/5xx responses including HTTP/1.1 reason phrases. Delimit the curl
error number so certificate failures such as curl 60 remain immediate.

Keep the existing three-attempt ceiling, 20/40-second backoff, checked CA
pair, pinned image, locked-install scope and kept-container exclusions.
Add controls using the observed curl 28/56 messages and refusal cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Codex <noreply@openai.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

General takeover and reviewed Stage 1 successor; select one ordinary source push/train. Both repo agents are Off. Their WIP refs are preserved. The stopped Server agent had already saved the exact proposed 2-file matcher/tests delta as 6da0d16a; I carried that delta into an isolated General branch without changing the WIP ref.

Head da97f4faa5900824b175afb7428684a4e72a000d, tree 241ad897932c7d76cd789e6e1c73888e743a0ccc, sole parent af5953504931c706079e7e8fb0e544a5e4158e2a. Successor delta 5569B / 9fe95d9de2efee742c13b16dee6a09b2cca1b706420d2334b890aa82a5a5871d; full against M 27709B / 71bc0212afc3e37dfa3fdff2fe342d31c8fab37262a5b621867e0705161797d7. No trust/image/sink/lock/workflow change in this successor. Backoff remains 20/40s and at most 3 attempts. The matcher accepts the actual curl 28/56 wording and bounded HTTP 429/5xx statuses, and refuses curl 60/404/403, updates and kept-container cases.

Independent source inspection plus the actual wrapper controls: 12 tests ran, 10 passed and 2 real-Docker controls skipped. Hard isolation confirmed an empty /run, private loopback/no route, absent Docker socket/home and refused TCP; no daemon or external network was used. Output hashes are retained privately. The first sandbox invocation refused before tests because --unshare-user was missing; it is retained, and the corrected isolated invocation passed. Diff whitespace and secret scan pass; worktree clean.

GitHub's official incident overlaps the failures: reported 10:36, latest 11:56 says API degradation mitigated/monitoring. This does not attribute every error or guarantee hosted recovery. This push repairs a concrete missed-retry defect; it is not a waiver. Contracts and PHPUnit's combined install/test command remain outage-exposed outside Stage 1.

Select one fast-forward push onto the existing draft PR, leased on exact old head af5953504931c706079e7e8fb0e544a5e4158e2a, before 12:55 UTC. Re-read this body/hash, actual main=M, remote/PR head, clean tree, delta and terminal attempt 4 before effect. Rewrite the title/description around the final CI-stability scope. One fresh normal train; no old-run retry, cancel, ready/queue, merge, release or local container. Keep all four NONPASSs. Required report: exact-head full checks, the repaired and fired-refusal tests across actual backend lanes, CLI producer/consumer receipts, Composer retry behavior and missing coverage. Report by T0+110min; a watcher observation deadline does not authorize cancelling GitHub work.

@rmcdaniel rmcdaniel changed the title Stabilize Shared Server fixtures: verified shared parity CLI transport and a deterministic timer-test repair Stabilize Native CI downloads and the past-deadline timer test Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General T0: one successor push, 2026-11-08T12:41:39.839977+00:00. Selection 6721619365 consumed once; fast-forward old-head lease af595350 → da97f4fa. The git remote and PR now both read da97f4faa5900824b175afb7428684a4e72a000d, tree 241ad897932c7d76cd789e6e1c73888e743a0ccc; draft, no queue. The first immediate PR API read still returned the old head after git had confirmed the new one. I made no additional push; the fresh API read confirms the new head.

The 2-file Composer matcher/tests successor carries the stopped agent's saved delta, with its WIP refs preserved. Stage 1 has 10 local wrapper-test passes and 2 real-Docker skips. Full CI is the required proving run; the current contracts and PHPUnit install paths remain outside this wrapper's retry protection. All four earlier NONPASSs stay attributed.

Fresh normal runs:

General owns observation and the terminal report by T0+110min (14:31:39 UTC). No cancel, old-run rerun, successor push, ready/queue, merge, release or local container is selected by this record. The repaired timer and fired-refusal backend controls, corpus consumers and exact-head checks are still owed. Runner #1101 and optimization #1099 remain deferred; M/D unchanged. Full Cloud health remains due 13:58/alert and takes precedence over waiting on CI.

The expanded retry comment moved the Composer command two lines farther
from its unchanged Brotli-image guard. The security inventory correctly
refused that unrecorded distance in the Repository contracts job.

Keep the explanation within the original five-line block, preserving the
existing exact guard distance without changing the registry, classifier,
CA pair, image, retry matcher or execution policy. Inventory and wrapper
controls pass together locally; real-Docker controls remain hosted.

Co-Authored-By: Codex <noreply@openai.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Attempt 5 source finding identified; a local successor is prepared, not pushed. Head da97f4f's Repository contracts job 128734068086 failed ComposerInventoryTest.test_every_sink_keeps_its_recorded_guard. The OpenAPI dependency installation passed in this job.

My expanded comment moved the unchanged Composer command two lines relative to its unchanged Brotli-image guard. The registry requires distance 20 and source now has 22. The gate correctly refused it. I had run the wrapper class locally but missed the inventory class; this is a source-validation gap, not an infrastructure classification.

Local correction b14296f4962a299198fc6b14d5648aef9c2ccde1, parent da97f4faa5900824b175afb7428684a4e72a000d, tree 583968b777eed67686f05e0d4e6ac3ed8e2bc86b: keep the explanation within the original five-line block. Delta 1393B / 92dbef89a5af4a4f8926812c7d9aa97a8400b986bed4610be3d1187c7d3c2c47. No logic, registry, classifier, image, trust or sink change. The matcher and 20/40s backoff are unchanged. The exact original guard distance is restored.

Expanded meaningful local checks now include both inventory and wrapper classes: 19 tests, 17 pass, 2 real-Docker skips, in the same hard-isolated namespace with no daemon/network. Inventory removal and unconfined-sink negatives pass; no guard was weakened. stderr hash 0a4820b0fe3e5a766906e60743f2f0c417884fb8ce4f2b66d0d42edf73afea81.

The current train is still live. No cancel, rerun or successor push; wait for its terminal state so a new push cannot cancel evidence. General owns the terminal audit and any separately selected successor. Attempts 1–4 remain NONPASS; attempt 5's final record will include this finding and all remaining lanes.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Attempt 5 terminal NONPASS; select one reviewed successor source push. General owns this work while both repo agents are Off.

Exact old head da97f4faa5900824b175afb7428684a4e72a000d is terminal: 63 checks, 60 success, 2 failure, 1 intended skip; all 6 runs finished on attempt 1. The only failures are Repository contracts' guard-distance finding and its Feature source qualification aggregate. No infrastructure failure is observed on this train. Shared Server fixtures run 42481449315 passed 48/48 jobs. The OpenAPI dependency install, PHPUnit suite, Sonar and CodeQL succeeded.

Retained artifact text proves both named controls passed on all 6 selected database profiles (SQLite, MySQL 8.0/8.4, MariaDB 10.11, PG 16/17): a_reopen_after_the_anchor_is_due_immediately_at_the_anchor and a_wake_turn_finishing_after_its_fired_deadline_is_refused. I inspected the actual ... ok lines. The original API job logs omit them because cargo stdout is redirected to retained files; test-list membership alone is not counted as execution. SQLite reports 748 pass/0 fail/1 ignored; each external backend's B shard reports 374/0, with the fired-refusal test's actual pass in its A shard. Artifact IDs, ZIP hashes, member lists and lines are retained privately. This proves the #1105 test target compiled/executed on this head, without making the whole head green.

Successor: b14296f4962a299198fc6b14d5648aef9c2ccde1, sole parent da97f4faa5900824b175afb7428684a4e72a000d, tree 583968b777eed67686f05e0d4e6ac3ed8e2bc86b. Delta 1,393B / 92dbef89a5af4a4f8926812c7d9aa97a8400b986bed4610be3d1187c7d3c2c47. Full against M 27769B / 0d390cfd15502250748cebf03251072a1e8769ba7c88373c352354228b06101e. It only restores the comment block's original height, so the unchanged Brotli guard stays at the already-recorded distance 20. No registry, classifier, CA, image, matcher, backoff or runtime change. Both relevant local classes pass together: 17 tests pass, 2 real-Docker controls skipped, with isolation proven. Whitespace check passes; worktree clean. All WIP refs are preserved.

Select one fast-forward push to the existing draft PR, leased on exact old head, starting before 13:30 UTC. Re-read this body/author/hash; require main=M, exact remote/PR old head, clean source and all old runs terminal. Keep the existing final scope/title, update the attempt count and source-finding disclosure. One fresh normal train; no old-run rerun, cancel, ready/queue, merge, release or local container. Report terminal exact-head checks and backend/corpus coverage by T0+110min. All attempts 1–5 remain NONPASS. Runner #1101 and optimization #1099 stay deferred; release M/D unchanged. Cloud full health remains due 13:58/alert.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Attempt 6 T0, General: one fast-forward push at 13:18:42.426378 UTC under selection 6721988340. Remote and PR head both equal b14296f4962a299198fc6b14d5648aef9c2ccde1, draft. Exact old-head lease on da97f4f; no earlier run was live and no cancellation occurred.

Fresh runs, attempt 1 only:

  • Shared Server fixtures 42484353157;
  • PHPUnit Feature 42484353126;
  • SonarQube 42484353198;
  • dynamic CodeQL 42484348431;
  • Public Boundary 42484353189 and push 42484348032.

At 13:35 the Repository contracts check passed, confirming the corrected layout satisfies the unchanged guard inventory. Other backend work was still running, so this is not a whole-head PASS. Attempts 1–5 remain NONPASS with their exact findings. Report ceiling 15:08:42 UTC; General owns observation. No ready/queue/merge/publication selected. Cloud full health by 13:58/alert takes priority over waiting on CI.

@rmcdaniel

Copy link
Copy Markdown
Member Author

General source acceptance and one ordinary queue selection for #1104. Both repo agents are Off; General owns this integration and preserves every WIP ref.

Accepted exact head b14296f4962a299198fc6b14d5648aef9c2ccde1, tree 583968b777eed67686f05e0d4e6ac3ed8e2bc86b, base/merge-base M 2a15179f29801eec9f2a2d4e6a9c5f93233f104e. Full delta 27769B / 0d390cfd15502250748cebf03251072a1e8769ba7c88373c352354228b06101e. PR description SHA256 ac1e8ac896134a29180999d548e4d35ce0a2bcea2b21ff36dea79e66b368dae6. It covers verified shared CLI download, the real Composer transport-error matcher and the deterministic debug-build timer-test seam. Comment-layout successor restores the unchanged guard distance; registry/trust/runtime contracts are unchanged. The API fallback's live availability is still unproved and no availability guarantee is claimed.

Exact-head train is terminal: 62 success, 1 intended skip, 0 failures, 0 statuses; all 6 runs successful on attempt 1. Required PHPUnit feature suite, Shared Server fixtures result and SonarCloud checks pass. Repo contracts now pass the full inventory; all backend/corpus coverage ran. Earlier da97's named past-A and fired-refusal controls passed on all 6 database profiles; current b142 has byte-identical Rust and its complete suites pass. Local inventory/wrapper controls 17 pass, 2 real-Docker skips; hosted checks supply the required runtime coverage. Attempts 1–5 remain NONPASS with exact findings.

Fresh GraphQL preflight is draft/OPEN, MERGEABLE/CLEAN, no auto-merge, no queue entry, empty queue. Select one mark-ready and one normal enqueue with expectedHeadOid=head after re-reading this raw body/author/hash and rechecking main, head, full delta, check/status inventory and empty queue. Start before 14:00 UTC. Ceiling: 45min after actual enqueuedAt. If that exact entry is still live at the ceiling, one exact dequeue after matching its ID/head; no re-entry or run cancellation.

Observer is read-only except that bounded dequeue. After merge, require valid GitHub signature, ordered parents [M,head], tree equal to the accepted head, exact applied delta, and actual-main terminal checks. Delete only the owned topic after those gates and ancestry checks; keep all WIP refs. Main drift or any unknown/refusal stops effects and preserves evidence. General owns the report and custody.

No tag, build, image/alias/publication, runner dispatch or runtime acceptance follows from this queue selection. Release 3.3.0 stays at M/D; runner #1101 and optimization #1099 are excluded. Full Cloud health by 13:58/alert takes priority; a health read does not authorize extending the queue ceiling.

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 8, 2026 13:44
@rmcdaniel
rmcdaniel added this pull request to the merge queue Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

Queue T0 — General. Selection 6722253782 consumed once. Marked ready, then one ordinary enqueue with expectedHeadOid=b14296f4. Entry MQE_lQDOSATFBs8AAAABNpAH084ABPZYzgPQwho, state QUEUED, position 1, enqueuedAt 2026-11-08T13:44:46Z. Exact ceiling 14:29:46 UTC, matching the saved entry timestamp plus 45min.

Final guards: main/base M; exact head b14296f/tree 583968b7; 63 checks all terminal (62 success,1 intended skip), 0 statuses; three required checks green; MERGEABLE/CLEAN; no auto-merge; empty queue before entry. All prior NONPASSs remain attributed.

General owns watch-only custody, with the one exact dequeue at the ceiling only if this same entry is still live. No re-entry, run cancellation, tag or publication. Runner #1101 and optimization #1099 excluded. Cloud full health by 13:58 remains the next timed obligation.

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General — #1104 ordinary queue entry is terminal NONPASS. GitHub removed it at 14:07:43 UTC (failed_checks); no dequeue, cancellation, re-entry or retry was performed. Main remains 2a15179. The PR is open/ready and the queue is empty.

Merge group 43edf47 has ordered parents [2a15179, b14296f] and the accepted tree 583968b7. Shared run 42486430061 failed only execution-and-codec (corpus-b) and its result aggregate; its other 46 jobs succeeded. The PHPUnit Feature and Boundary merge-group runs passed.

The failed job is 128750154928. At 13:52:38 the published PHP reference recorder threw Large command batches: no workflow task for select_key_overflow. This happened before the Native recording and comparison. The retained PHP failure excerpt confirms the same exception; its middleware reports 20 backend-lock-pressure poll retries across the recorder, but does not attribute them to this particular poll. The last poll HTTP status/body was not retained. The cause therefore remains unproved; this is not classified as another Composer download outage or a Native regression.

Artifact 13619991995 binds ZIP sha256 e967386a852b73fba542f83b0c6e7574416cd064be4d1c005fbea016b92eb1f6. All existing source-train results and earlier NONPASSs remain attributed. The CLI producer and consumers, six native-test backends, and the remaining corpus jobs passed in this merge-group invocation.

Next: retain bounded status/refusal/task-shape diagnostics at this existing poll assertion, with focused valid-claim and refusal controls; then review the exact source successor before a fresh normal train. No assertion, fixture, retry limit, reference image or Native runtime is weakened. #1101 and #1099 remain deferred; the 3.3.0 cut/tag/image remain bound to M.

The frozen PHP reference can finish the large-command-batches poll without
a task. Preserve that assertion and include the final HTTP status, refusal
shape and retries attributable to this poll, without headers or payloads.
The previous merge-group failure did not retain those facts, so its cause
remains unproved. No fixture, retry budget or runtime behavior changes.

Co-Authored-By: Codex <noreply@openai.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

General selects one fresh normal source train on #1104 for head 7697b46 / tree e18bc4ad963f09877d1817bbe2881a53153b8ed4, sole parent b14296f. The successor is exactly two conformance-diagnostic files: 6674 B / sha256 a9862c805d87ca1fbfcd1ea8a33792a895750713beabe2aa2ee4be6b6bccedcd. Full delta from M: 34443 B / 2f37b133fcf02fb1dd1fb6086c7e5d1ee9adc8438eeaf6158b52cbaa91b1ff25.

The ordinary queue entry ended NONPASS at 14:07:43 (record 6722556394). The frozen PHP recorder failed before Native comparison; its final poll response was not retained, so the cause stays unproved. This successor preserves the existing is-array claim assertion and captures only bounded HTTP/refusal/shape facts plus retries for that specific poll. It changes no fixture, retry budget, reference image or Native behavior.

Local PHP 8.4.27 checks: both files lint; two valid claims return unchanged; five refusal shapes retain the required facts without payload/header values, with messages below 1 KiB. One cached network-none, read-only, UID-1000 tooling container exited 0 with empty stderr; exact ID/name/run-label absence is proven. Actual PHPUnit execution remains hosted.

Before the push: require main and merge-base M, clean exact head/tree/delta, remote and PR old head b14296f, and all prior source runs terminal. Mark the PR draft and push once with the exact old-head lease. Keep all prior NONPASSs and the queue failure. No rerun/cancel, ready/queue, release, runner change or #1099 effect is selected. Return per-check terminal evidence; the new diagnostic does not itself qualify a previously failed assertion.

@rmcdaniel
rmcdaniel marked this pull request as draft November 8, 2026 14:17
@rmcdaniel rmcdaniel changed the title Stabilize Native CI downloads and the past-deadline timer test Stabilize parity downloads and retain deterministic failure evidence Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General — one successor push completed at 14:17:47 UTC under selection 6722598138 (raw-body sha256 cffb470805b683326b4ad60fc004d95da6812a27271678ad6f599af87b492ca4). Exact old-head lease b14296f → 7697b46; plain fast-forward. Remote and PR now agree on head 7697b46 / tree e18bc4ad, draft and out of the queue. Main remains M. The first immediate PR readback lagged behind the pushed branch; a read-only follow-up confirmed the expected head and draft state. No second push occurred.

Successor delta: 6,674 B / a9862c805d87ca1fbfcd1ea8a33792a895750713beabe2aa2ee4be6b6bccedcd. Full delta from M: 34,443 B / 2f37b133fcf02fb1dd1fb6086c7e5d1ee9adc8438eeaf6158b52cbaa91b1ff25. Two conformance-diagnostic files only. All prior NONPASSs remain unchanged.

Normal runs: Shared fixtures 42489107309; PHPUnit Feature 42489107293; SonarQube 42489107187; CodeQL 42489104065; Boundary 42489107167 plus push 42489102742. No queue, cancellation, workflow rerun, release or runner-ref effect. General will classify terminal results before integration.

rmcdaniel and others added 2 commits November 8, 2026 14:41
The feature job selects its Unit tests explicitly. Include the new
diagnostics class so its four tests execute in normal PR, merge-group
and main verification. The previous green run did not execute that class.

Co-Authored-By: Codex <noreply@openai.com>
The inventory correctly detects a changed full shell line, although its
only semantic change is one extra PHPUnit class after Composer finishes.
Re-review that line with the same sink count, guard, distance and trust
confinement. Do not change the classifier or any execution permission.

Co-Authored-By: Codex <noreply@openai.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

General selects one wiring successor push on the existing draft #1104. Head d8d40e5, tree fa4163bca3c244450a55ad2ff44b45f10fba307d; two commits on old remote 7697b46: dd2affe and d8d40e5. The successor is 9212 B / 664c9e833eebd5609354d71658b0663d181ad7504b8803f363aa6322edcce94b; full delta from M is 43655 B / c7bcfd981608757c01715c5ad2c30127a08e72cef0b69b27c16d1e709097c505.

The 7697b46 source train completed with 62 success, one intended skip, zero statuses. Its results remain valid. It did NOT execute the new four-method diagnostic test class because the PHPUnit Feature command selects Unit classes explicitly. General missed that wiring when adding the class; no queue action was taken.

This successor adds that class to the existing PHPUnit invocation. The Composer inventory then correctly refused the changed full shell line locally. Re-review confirms the only command change is a PHPUnit filename after Composer finishes: the same two Composer occurrences, source-free checked tool image, server-verify guard and distance 86 remain exact. The one manifest line is updated; the classifier, trust boundary, permissions, sink count, CA, image, installs and retry policy do not change. No waiver.

Local hard-isolated Inventory + RunComposer controls: 19 run, 17 passed, two real-Docker checks skipped; the initial unreviewed-line refusal is preserved. Existing PHP functional/lint checks and all preceding source/queue attributions stay recorded.

Recheck clean exact head/tree/delta; main and merge-base M; PR/remote old head; all prior runs terminal; no queue or auto-merge. Push once with the exact old-head lease and let normal CI execute the four new tests. No rerun/cancel, ready/queue, release, runner-ref or #1099 effect is selected.

@sonarqubecloud

sonarqubecloud Bot commented Nov 8, 2026

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

General — one wiring successor push completed at 14:47:52 UTC under selection 6722918514 (raw body 7997e3932865c0e32074e910bfb6774769f6dbed2453cf925ce5d387cbc221c9). Exact old-head lease 7697b46 → d8d40e5, plain fast-forward. Remote and PR agree on d8d40e5 / tree fa4163bc; draft and out of the queue. Main remains M.

Exactly two files since 7697b46: the explicit PHPUnit class list and its reviewed Composer inventory line. Successor 9,212 B / 664c9e833eebd5609354d71658b0663d181ad7504b8803f363aa6322edcce94b; full 43,655 B / c7bcfd981608757c01715c5ad2c30127a08e72cef0b69b27c16d1e709097c505. Composer confinement count/guard/distance and every runtime assertion are unchanged.

Normal runs: Shared fixtures 42491566759; PHPUnit Feature 42491566827; SonarQube 42491566807; CodeQL 42491562962; Boundary 42491566898 and push 42491563208. The four new PHPUnit methods must be verified on this head before integration. The earlier 7697b46 train stays green with its disclosed new-test execution gap; prior NONPASSs and the failed queue invocation remain attributed. No cancellation, rerun, queue, release or runner update occurred.

@rmcdaniel

Copy link
Copy Markdown
Member Author

General accepts the exact #1104 source head d8d40e5, tree fa4163bca3c244450a55ad2ff44b45f10fba307d, on base/merge-base M 2a15179. Full delta 43,655 B / c7bcfd981608757c01715c5ad2c30127a08e72cef0b69b27c16d1e709097c505. Worktree clean; no new source change is selected.

Exact-head terminal result: 62 success, one intended path-gated skip, zero statuses. All three required checks are green. Shared fixtures 42491566759 passed; PHPUnit Feature 42491566827 passed, including the explicitly selected ServerParityLargeCommandBatchesProbeTest.php in job 128764935529 (main invocation: 3,633 tests / 90,112 assertions, 51 skips). Its four new methods have no skip or group condition. Sonar and CodeQL passed. The earlier 7697b46 train stays green with its disclosed missing-test execution gap. Source NONPASSs and the 14:07 failed merge group remain attributed.

Select one fresh ordinary queue entry after re-reading this body and rechecking main/base/merge-base M; exact head/tree/delta; open/draft/mergeable/clean; no auto-merge; these terminal checks/statuses; and empty queue. Mark ready once, then enqueue once with expectedHeadOid=d8d40e5e. No forced/bypass merge, cancellation or workflow rerun. Set a 45-minute ceiling from the actual enqueue timestamp; if this exact entry remains live then, perform one exact dequeue and stop that entry. Do not silently re-enter.

After merge require valid signature, ordered parents [M,d8d40e5e], tree equality to fa4163bc, actual-main terminal check/status custody and ancestry. Delete only the owned ci/parity-cli-once topic, with exact-head/ancestry/main-terminal guards; preserve all WIP refs. Return custody. The 3.3.0 cut/tag/image stay bound to M; frozen runner #1101 and optimization #1099 are excluded. No tag, publication, acquisition, qualification dispatch or alias effect is selected here.

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 8, 2026 15:22
@rmcdaniel
rmcdaniel added this pull request to the merge queue Nov 8, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

General — fresh ordinary queue entry created once under selection 6723285934 (2cbb48d8fbcde15e49c9043568e0c42bd9a723896193991cb8dc184c0286a075). Final guards matched: main/base/merge-base M, head d8d40e5, tree fa4163bc, full delta c7bcfd98, clean worktree, 62 success + intended skip, zero statuses, no auto-merge and empty queue.

Marked ready once and enqueued with expectedHeadOid=d8d40e5e. Entry MQE_lQDOSATFBs8AAAABNpAH084ABPZYzgPQ_Is, enqueuedAt 2026-11-08T15:22:59Z, initial state QUEUED, position 1. Ceiling 2026-11-08T16:07:59+00:00. Watch only; one exact dequeue if this same entry remains live then. No silent re-entry.

The prior b14296f merge-group failure remains recorded at 6722556394. The d8d40e5 source train is terminal green, including the now-wired four diagnostic tests. Main custody is still owed; no release, runner refresh/dispatch, image or #1099 effect was performed by this queue action.

Merged via the queue into main with commit f77b093 Nov 8, 2026
63 checks passed
@rmcdaniel

Copy link
Copy Markdown
Member Author

General: #1104 second queue entry merged at 15:46:30Z, inside its 16:07:59Z ceiling, with no dequeue/re-entry/rerun/cancel.

Actual main C = f77b093. GitHub signature is valid; ordered parents are [M 2a15179, accepted head d8d40e5]; tree fa4163bca3c244450a55ad2ff44b45f10fba307d equals the accepted head. The actual M→C binary diff is byte-equal to the accepted delta: 43,655 B / c7bcfd981608757c01715c5ad2c30127a08e72cef0b69b27c16d1e709097c505. Main readback is C.

The merge-group runs passed. Actual-main push checks are running, so custody is not yet terminal. The owned topic stays until main is terminal and successful, then exact-head/ancestry cleanup. All WIP refs remain untouched. Earlier NONPASSs and the initially missing PHPUnit wiring remain attributed.

Next: terminal actual-main custody, then review/select the unchanged #1101 runner merge on top of C. Native 3.3.0 tag/image remain bound to M; #1099 stays deferred. No tag, publication, runner dispatch or alias effect is selected by this merge receipt.

@rmcdaniel
rmcdaniel deleted the ci/parity-cli-once branch November 8, 2026 16:01
@rmcdaniel

Copy link
Copy Markdown
Member Author

General returns terminal #1104 actual-main custody at 16:01:45Z.

C = f77b093 remains current main. Valid signature; ordered parents [M 2a15179, d8d40e5]; tree fa4163bc equals the accepted head. The 43,655 B / c7bcfd98 delta is byte-equal to the accepted full diff. All 79 check runs are terminal: 71 success, 8 expected skips, 0 failures/cancelled/timed-out; 0 statuses.

After main-success, exact-head and ancestry guards, the owned ci/parity-cli-once topic was deleted once with the d8d40e5 lease. Git readback is empty and API is 404. No WIP/preparation ref was touched.

Delivered: bounded pinned parity-CLI acquisition shared to consumers; Composer 2.10 transient transport matching; deterministic #1105 timer hold/control; bounded missing-poll diagnostics and their explicit PHPUnit wiring. API fallback availability remains unproven; no broader outage or zero-flake claim. All earlier NONPASSs and the initially unexecuted test-class gap stay attributed.

Next: unchanged #1101 runner merge on top of C, as a new ordinary queue entry. Native 3.3.0 release M and image D stay unchanged; #1099 deferred. No dispatch, tag, alias or publication by this custody receipt. Both repo agents remain Off.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shared Server fixtures: fetch the verified parity CLI once instead of in every corpus job

1 participant