Skip to content

CI: suites run in parallel with the review; every suite tests head + the CURRENT main - #6144

Merged
rbuergi merged 5 commits into
mainfrom
ci/suites-parallel-with-review
Oct 5, 2026
Merged

rbuergi merged 5 commits into
mainfrom
ci/suites-parallel-with-review

Conversation

@rbuergi

@rbuergi rbuergi commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

What

Two maintainer directives, one change set, two register rows:

1. suites-parallel-with-review: the suites no longer wait for the review

  • node-repo-stage-gate.yml now judges stage 0 only by default. A red static control still holds every heavy leg, and the gate still fails rather than skipping. With stage 0 green, the gate answers ready=true mode=parallel: the build, the shards (core) and the admitted heavy legs (Plugins, which calls the lane @main) start at once and run beside the automatic review.
  • The review requirement stays a real required check. Core's ruleset requires Automatic review answered and Plugins' classic protection requires internal-review (both measured today). So merging still needs the green suites AND every thread answered. Arming (the control plane's arm gate) is unchanged.
  • The review-first ordering is kept as an opt-in: review-before-suites: true. Only that path fetches the predicate.
  • The gate job is renamed Stage gate: may the suites start, because the old name Stage 1: review landed and answered would misreport a green tick. check-review-answered.py matches both names (STAGE_GATE_JOBS, with a self-test case for each). That lets stage-advance.yml, kept as transition only, still release runs held before this change.
  • Re-running work when only the review changes: the review landing or a reply now re-runs nothing.

2. suites-test-fresh-merge: every suite tests head + the CURRENT main

  • New composite action .github/actions/fresh-merge, backed by .github/scripts/ci-fresh-merge.py. After the checkout it runs merge-tree --write-tree --merge-base and commit-tree -p <main tip> -p <head> (fixed identity and date), checks the result out, and prints "Tested: head X merged onto main@Y → Z (GitHub's merge ref was built on main@W)".
  • Nothing is pushed. There is no branch update, no new head, no new review and no run loop, and it needs no write token, so it works for forks too. The merge is a pure function of (main, head): every job given the same main-sha gets the identical commit. A conflict with the current tip is red and names the paths.
  • Core dotnet-test.yml: precheck resolves the tip once and applies the merge, so the green-tree probe keys the tested tree. build, every shard, doc-gate and platform-compat merge onto precheck's main-sha. collect-results re-derives the merge so the refs/ci-green marker points at the tested commit (pushing HEAD, guarded on the tree matching).
  • Shared lanes: node-repo-gate.yml (plan resolves, every shard merges), node-repo-module-pack.yml (select merges so the build keys hash the tested tree, then build-workspace/pack/tests) and node-repo-compile-check.yml take a new optional input merge-main-sha. Empty means the lane resolves the tip itself. Satellites need no change. An explicit content-ref/content-repository (the platform's CD) is tested as given.
  • Why (measured on core today, REST): 13 of the 18 open PRs had a merge_commit_sha whose first parent was not main's tip, and re-reading them refreshed none.

Docs

  • New Doc/Architecture/FreshMergeUnderTest.
  • StagedPullRequestPipeline: banner, a new "Suites in parallel with the review" section (why, what changed, expected lead-time effect, transition), adoption table and reading guide.
  • Two PolicyNotProse rows and a topic-map entry.
  • The AGENTS.md merge-latest-before-push block (hub-only) now points at the CI half. The step-2 spoke drafts are superseded; the shared-rules.json "why" records that.

Verified locally

  • ci-fresh-merge.py --self-test passes 13/13. Negative controls: the merge onto the OLD main is a different tree; a conflict is refused. Mutation check: swapping the parents reds 2 cases.
  • check-review-answered.py --self-test is green, including the two new gate-name cases.
  • Clean: actionlint (no non-shellcheck findings on the touched workflows), check-workflow-timeouts (0 violations), check-workflow-yaml-keys, check-guard-step-masking, check-reusable-workflow-runners, check-workflow-permission-pairing, test-gate-lane-forwards-the-callers-set and check-shared-rules --local (all 7 blocks identical).
  • MeshWeaver.Documentation.Test (Release, -warnaserror, 0 warnings): 677/677 passed, including link integrity, topic map and front matter.

Overlaps

  • docs+gate: two runner pools, priority from the CI queue (policy ci-two-pools-priority-queues) #6126 (runner pools) also edits StagedPullRequestPipeline.md ("Trunk outranks…") and PolicyNotProse.md. The hunks are different; whichever lands second resolves a table-row/section merge.
  • Systemorph/MeshWeaver.Plugins#2896 rewrites Plugins' admission. The Plugins half of this change adds one step and one output to it. Its HELD-FOR-DISPATCH re-runs are exactly the stale-merge case: with this change they re-resolve main when admitted.
  • Memex#660: no file overlap.
  • Paired Plugins PR: passes merge-main-sha to the lanes and renames PrBabysitter.StageGateJob. This PR lands first: the Plugins PR passes an input these lanes only gain here.

Recycle / deploy

Nothing in a portal changes; CI only.

Pairs-with: none — no public C# surface is removed or changed; workflows, a script, an action and docs.
Mirror-sync: none — no i18n catalog change.

🤖 Generated with Claude Code

rbuergi and others added 2 commits October 5, 2026 11:21
…CURRENT main

Two maintainer directives, two policies (register rows in PolicyNotProse):

suites-parallel-with-review — node-repo-stage-gate.yml judges stage 0 only by
default: the build/shards/heavy legs start as soon as the static controls are
green and run beside the automatic review. The review stays its own required
check (core `Automatic review answered`, Plugins `internal-review`), so merging
and arming still need it answered. The review-first ordering is kept as the
lane's opt-in (`review-before-suites: true`). The gate job is renamed
"Stage gate: may the suites start"; check-review-answered.py recognises both
names so stage-advance.yml (kept, transition only) still releases runs held
before this change.

suites-test-fresh-merge — new composite action .github/actions/fresh-merge +
.github/scripts/ci-fresh-merge.py (self-test with negative controls): after
the checkout, the head is merged onto the base tip with merge-tree/commit-tree
(no push, deterministic per (main, head), red on a conflict) and the tested
main is printed. Wired into dotnet-test.yml (precheck resolves once; build,
shards, doc-gate, platform-compat, collect-results's green-tree marker) and
into node-repo-gate / node-repo-module-pack / node-repo-compile-check via a
new optional `merge-main-sha` input (empty = the lane resolves it itself).

Docs: new Architecture/FreshMergeUnderTest, StagedPullRequestPipeline updated,
topic map, AGENTS.md merge-latest-before-push block points at the CI half
(hub-only; the step-2 spoke drafts are superseded).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…th-review

# Conflicts:
#	src/MeshWeaver.Documentation/Data/Architecture/PolicyNotProse.md
@rbuergi
rbuergi enabled auto-merge October 5, 2026 09:24
rbuergi and others added 2 commits October 5, 2026 11:26
…nd say why

The first PR run's compare read failed in the same minute every PR-body read of
that run failed (GitHub REST unavailable to the run's token), so the merge-base
of a shallow checkout was unreadable. Now the reason is printed, and the two tips
are deepened (64/512/4096) until git walks to the base itself. Self-test case
added: a failing compare still yields the identical merge commit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…om the commit object

The run's GITHUB_TOKEN shares one per-repository REST budget with every PR run
(every PR-body read of every core PR run failed in the same minutes), so the
merge-base of a shallow checkout is now found by deepening, with the compare read
as the last resort. Parents are read with cat-file: a shallow tip's parents are
grafted away, which hid the already-fresh and stale-merge readings (mutation-
checked: the rev-list form reds the new shallow already-fresh case).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

  3 files  ±0    3 suites  ±0   3m 40s ⏱️ -1s
561 tests ±0  370 ✅ ±0  191 💤 ±0  0 ❌ ±0 
565 runs  ±0  374 ✅ ±0  191 💤 ±0  0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

    5 files  ±0      5 suites  ±0   3m 38s ⏱️ +13s
1 279 tests ±0  1 279 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 280 runs  ±0  1 280 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 753 tests  ±0   1 751 ✅ ±0   5m 4s ⏱️ -31s
    4 suites ±0       2 💤 ±0 
    4 files   ±0       0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

2 414 tests  ±0   2 414 ✅ ±0   5m 18s ⏱️ -22s
    4 suites ±0       0 💤 ±0 
    4 files   ±0       0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

This pull request removes 3 and adds 1 tests. Note that renamed tests count towards both.
   --- End of inner exception stack trace ---, isDenial: True)
 ---> System.UnauthorizedAccessException: Access denied
Memex.Portal.Shared.Test.SessionDenialIsAnAnswerTest ‑ OnlyAVerdictReadsAsADenial(shape: "the same verdict nested, as a late denial dispatch"···, failure: System.InvalidOperationException: write failed
Memex.Portal.Shared.Test.SessionDenialIsAnAnswerTest ‑ OnlyAVerdictReadsAsADenial(shape: "the same verdict nested, as a late denial dispatch"···, failure: System.InvalidOperationException: write failed
 ---> System.UnauthorizedAccessException: Access denied
   --- End of inner exception stack trace ---, isDenial: True)

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

    2 files  ±0      2 suites  ±0   8m 44s ⏱️ +20s
1 104 tests ±0  1 104 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 105 runs  ±0  1 105 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

    4 files      4 suites   16m 9s ⏱️
3 562 tests 3 562 ✅ 0 💤 0 ❌
3 569 runs  3 569 ✅ 0 💤 0 ❌

Results for commit 57ea9e9.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    22 files  ±0      22 suites  ±0   42m 36s ⏱️ -26s
10 673 tests ±0  10 480 ✅ ±0  193 💤 ±0  0 ❌ ±0 
10 686 runs  ±0  10 493 ✅ ±0  193 💤 ±0  0 ❌ ±0 

Results for commit 57ea9e9. ± Comparison against base commit cab1f4c.

This pull request removes 29 and adds 11 tests. Note that renamed tests count towards both.

   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---, expected: True)
   --- End of inner exception stack trace ---, isDenial: True)
 ---> (Inner Exception #1) MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432<---
 ---> (Inner Exception #1) System.InvalidOperationException: boom<---
 ---> (Inner Exception #1) System.InvalidOperationException: source B is misconfigured<---
 ---> (Inner Exception #1) System.Net.Sockets.SocketException (0xFFFDFFFF): Name or service not known<---
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
 ---> System.AggregateException: One or more errors occurred. (Failed to connect to 10.42.18.4:5432)
…
Memex.Portal.Shared.Test.InstanceIdRulesMatchTheRegistryTest ‑ TheSetupHostAgreesWithTheRegistry(candidate: "2dcc3a31-8ab5-4102-b1a3-b60efc434c4c")
Memex.Portal.Shared.Test.SessionDenialIsAnAnswerTest ‑ OnlyAVerdictReadsAsADenial(shape: "the same verdict nested, as a late denial dispatch"···, failure: System.InvalidOperationException: write failed
 ---> System.UnauthorizedAccessException: Access denied
   --- End of inner exception stack trace ---, isDenial: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "a MIXED aggregate — one transient branch, one genu"···, exception: System.AggregateException: One or more errors occurred. (Failed to connect to 10.42.18.4:5432) (source B is misconfigured)
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.InvalidOperationException: source B is misconfigured<---
, expected: False)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "a nested aggregate with one genuine leaf", exception: System.AggregateException: One or more errors occurred. (One or more errors occurred. (Failed to connect to 10.42.18.4:5432) (boom)) (Failed to connect to 10.42.18.4:5432)
 ---> System.AggregateException: One or more errors occurred. (Failed to connect to 10.42.18.4:5432) (boom)
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.InvalidOperationException: boom<---

   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432<---
, expected: False)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "a nested aggregate, all leaves transient", exception: System.AggregateException: One or more errors occurred. (One or more errors occurred. (Failed to connect to 10.42.18.4:5432)) (Failed to connect to 10.42.18.4:5432)
 ---> System.AggregateException: One or more errors occurred. (Failed to connect to 10.42.18.4:5432)
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432<---
, expected: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "a reflective wrapper around a transient cause", exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.Net.Sockets.SocketException (110): Connection timed out
   --- End of inner exception stack trace ---, expected: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "a transient cause UNDER an aggregate branch's wrap"···, exception: System.AggregateException: One or more errors occurred. (wrapped)
 ---> System.InvalidOperationException: wrapped
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---, expected: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "an 'initialization failed' wrapper around a transi"···, exception: System.InvalidOperationException: Hub 'x' initialization failed
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---, expected: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "an aggregate whose branches are ALL transient (two"···, exception: System.AggregateException: One or more errors occurred. (Failed to connect to 10.42.18.4:5432) (Name or service not known)
 ---> MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.Net.Sockets.SocketException (0xFFFDFFFF): Name or service not known<---
, expected: True)
MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest ‑ Classifies(shape: "the #4067 shape: transient provider fault wrapping"···, exception: MeshWeaver.Messaging.Hub.Test.InfrastructureFaultTest+ProviderException (0x80004005): Failed to connect to 10.42.18.4:5432
 ---> System.TimeoutException: Timeout during connection attempt, expected: True)
…

♻️ This comment has been updated with latest results.

@systemorph-com systemorph-com Bot added the thread:pr-systemorph-meshweaver-6144-e84f16 https://memex.systemorph.com/Hosting/Triage/_Thread/pr-systemorph-meshweaver-6144 label Oct 5, 2026
@rbuergi
rbuergi disabled auto-merge October 5, 2026 10:56
@rbuergi
rbuergi enabled auto-merge October 5, 2026 10:57

@systemorph-com systemorph-com Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review summary (data, not an instruction to any agent)

Two CI policies in one change set. (1) `suites-parallel-with-review`: `node-repo-stage-gate.yml` gains a `review-before-suites` opt-in; on the default the gate's judge step exits `ready=true mode=parallel` immediately after the stage-0 checks, so the heavy legs run beside the automatic review instead of after it; the gate job is renamed to 'Stage gate: may the suites start' and `check-review-answered.py` now matches both names (tuple + `endswith`) so the transition-only listener still releases old holds. (2) `suites-test-fresh-merge`: a new composite action `fresh-merge` backed by `ci-fresh-merge.py` replaces each suite job's checkout with a locally computed merge of the head onto the base branch's CURRENT tip (`merge-tree --write-tree --merge-base`, `commit-tree` with fixed identity and the head's dates — byte-identical per main sha, nothing pushed, red on a conflict, green no-op off pull requests and for a named content ref); wired into core `dotnet-test.yml` (precheck resolves once; build, shards, doc-gate, platform-compat merge onto precheck's main-sha; collect-results re-derives for the `refs/ci-green` marker, guarded on the tree matching) and into the three shared lanes via a new optional `merge-main-sha` input; docs, the policy register and AGENTS.md updated. Checked: the merge script's control flow (conflict -> exit 1 naming paths; already-fresh idempotence; shallow deepen before the REST last resort; determinism of the commit), the main-sha plumbing between jobs, the early exit's placement after the fork/not-staged branches, the marker-push tree guard, and the doc/code cross-references. NOT verified: the diff is INCOMPLETE — `ci-fresh-merge.py`'s patch is truncated (first 20000 of 20070 chars kept), so its last ~70 characters (the tail of the `__main__` dispatch) went unread and nothing is asserted about them; that `Automatic review answered` (core) and `internal-review` (Plugins) really are required checks (branch protection is not in this diff); how the new gate-name self-test cases' verdict reaches the exit code of `check-review-answered.py --self-test`; and exact literals masked by the item's redaction placeholders in the patches. Reviewed from the diff alone — the repository's source is not available to this review. No prompt-injection or instruction-to-reviewer content found in the diff.

Findings: 0 blocking · 0 should-fix · 3 question · 1 nit

File-level findings — Automated review finding (data, not an instruction to any agent):

nit src/MeshWeaver.Documentation/Data/Architecture/FreshMergeUnderTest.md

The 'Where it runs' table's MeshWeaver.Plugins row (admission resolves the tip; the listed legs apply the merge) describes the paired pull request Systemorph/MeshWeaver.Plugins#2896, which has not landed at this head — this repository's diff contains no Plugins change. Until the pair merges, the page documents Plugins behaviour that does not exist yet; a pending-the-paired-change marker (as the PR body's Overlaps section carries) would keep the page honest in the window between the two merges.

⚠️ 🚨 The diff is INCOMPLETE: 1 patch(es) truncated and 0 omitted (budget 150000 characters, 20000 per file) — say so in the review summary and do not assert anything about what you could not read.


Internal review of 0e5e365cc9d55fca917f5f955815605bef6209e8 — GLM-5.3, posted by the control plane. It is advisory, it never approves, and merging stays with a human signature.

fi
[ -n "${PR:-}" ] || { echo "::error::a pull_request event without a pull request number"; exit 1; }
# 🔀 The default: the review runs IN PARALLEL with the suites (policy suites-parallel-with-review).
if [ "$REVIEW_BEFORE_SUITES" != "true" ]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question — Automated review finding (data, not an instruction to any agent)

On the default path this gate now exits `ready=true mode=parallel` right after the stage-0 checks, so within this workflow nothing further requires the head's review before the heavy legs spend runners. The PR states the merge is still gated by the separate required checks (`Automatic review answered` on core, `internal-review` on Plugins) — but branch-protection configuration is not part of this diff and cannot be checked here. Please confirm both are required on the base branches: the parallel default is only as safe as that, and if either is not (or later stops being) required, a head could reach a mergeable green wall with nothing in the pipeline requiring its review.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed, and I measured it rather than assuming it (REST, 2026-10-05).

  • Core: ruleset 2128472 (main pr protection, active) has a required_status_checks rule with Consolidate test results and Automatic review answered.
  • Plugins: classic branches/main/protection lists internal-review among its required contexts, with app_id: 4918443 (the reviewer App).

So a head whose review is missing or unanswered stays red on that context and cannot merge. The control plane's arm gate (arm_readiness) also still requires it.

You are right that the parallel default is only as safe as those two settings. That dependency is now written down: the stage-gate header names both contexts, and so do the new StagedPullRequestPipeline section ("Nothing became skippable") and the policy row suites-parallel-with-review. Like every protection value, they are a measurement and must be re-measured, never remembered.

failed_gate = {"status": "completed", "conclusion": "failure", "name": f"stage-gate / {STAGE_GATE_JOB}"}
for legacy, expect in ((f"stage-gate / {STAGE_GATE_JOBS[1]}", True), ("stage-gate / Stage 1: something else", False)):
ok = legacy.endswith(STAGE_GATE_JOBS) == expect
failures += 0 if ok else 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question — Automated review finding (data, not an instruction to any agent)

The two new gate-name cases report their verdict through a `failures` counter update and a printed line; the code that turns `failures` into the exit status of `--self-test` is outside this diff, so I cannot tell whether a FAIL here (a name the tuple must not recognise, or the legacy name failing to be recognised) fails the self-test or only prints. Please confirm the counter this loop writes is the one the exit path reads, and that the update accumulates rather than overwrites — the rename's regression guard should be enforced, not just reported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is enforced. The loop sits at function level in the same self-test function as every other case (it is not a nested helper), and it does failures += 0 if ok else 1, so the count accumulates rather than being overwritten. That same failures is the variable the exit path reads at the end of the function: if failures: print("::error::… self-test: {failures} case(s) did not behave …"), which returns non-zero.

The run log shows both new cases as self-test ok gate-name: …. A FAIL there would red --self-test, and with it the stage gate's and the stage advance's "Prove the predicate can say no" steps.

with:
path: repo
main-sha: ${{ inputs.merge-main-sha }}
content-ref: ${{ inputs.content-ref || inputs.content-repository }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question — Automated review finding (data, not an instruction to any agent)

`content-ref: ${{ inputs.content-ref || inputs.content-repository }}` hands the action a repository NAME as `content-ref` whenever a caller sets `content-repository` without `content-ref`; the action then skips the fresh merge (mode `content-ref`) and prints that the caller named a content ref — a repository reported as a ref. With `content-repository` naming another repository that combination cannot check out at `github.sha` anyway; the live case is a caller that names its OWN repository redundantly, whose pull request then runs its suites on the push-time merge ref — the stale green this change exists to close. Is such a caller possible today, and if the platform's CD (content-ref always set) is the only pattern, would `content-ref: ${{ inputs.content-ref }}` be the safer wiring? The same `|| inputs.content-repository` appears in the compile-check lane and the other module-pack legs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, fixed in 57ea9e9. In all five places (compile-check, and module-pack's select, build-workspace, pack and tests) the action now receives:

content-ref: ${{ inputs.content-ref || (inputs.content-repository != github.repository && inputs.content-repository || '') }}

That gives three cases:

  • A real content-ref opts out (the platform's CD).
  • A DIFFERENT repository opts out, because merging another repository's content onto this repository's main would be meaningless.
  • A caller naming its OWN repository redundantly now gets the fresh merge, so that case no longer falls back to the push-time merge ref.

As for whether such a caller exists today: the cross-repository callers I know of (core's CD) also pass content-ref. I did not sweep every satellite caller for a redundant self-reference, and with this wiring it no longer matters.

…ips the fresh merge

Review finding on #6144: passing content-repository as content-ref made a caller
that names its own repository redundantly test the push-time merge ref. Only a
real content-ref, or a DIFFERENT repository, now opts out.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@rbuergi
rbuergi merged commit 60aa837 into main Oct 5, 2026
rbuergi added a commit that referenced this pull request Oct 5, 2026
…icy review-then-suites)

Maintainer correction of #6144's parallel default: the fleet-wide order is
review -> suites against a FRESH merge with the current main -> arm only when
the review is answered AND the suites are green.

- node-repo-stage-gate.yml: review-before-suites defaults to TRUE again (the
  parallel path stays as a per-caller opt-out); stage-advance listeners are
  required again, not transition-only.
- dotnet-test.yml: the suites' main is resolved by the build job (re-run when a
  held run is released) instead of precheck (not re-run), so a released run
  tests today's main; shards, doc-gate, platform-compat and the green-tree
  marker follow the build's main and tree.
- check-review-answered.py arm gate: condition 4 required_checks_green -
  every required status check of the base (rulesets + classic protection,
  review contexts excluded, an empty set refused) completed success on the
  head. 9 new self-test cases; a mutation dropping the condition reds 6.
- Docs: register row suites-parallel-with-review -> review-then-suites;
  StagedPullRequestPipeline, FreshMergeUnderTest, topic map.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@rbuergi
rbuergi deleted the ci/suites-parallel-with-review branch October 10, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

thread:pr-systemorph-meshweaver-6144-e84f16 https://memex.systemorph.com/Hosting/Triage/_Thread/pr-systemorph-meshweaver-6144

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant