Skip to content

Share one MultiEntryIndex across both compile_emission arms - #9549

Merged
briansrls merged 4 commits into
mainfrom
session/merry-koi-836
Aug 28, 2026
Merged

briansrls merged 4 commits into
mainfrom
session/merry-koi-836

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Stacked on #9548 (the root-anchoring fork repair), split out per ruling relayed 2026-08-28 because that defect can be wrong independently of anything here. This PR's diff is the sharing change alone.

The cost-shape defect

compile_emission is the one compilation transaction, and it is the producer behind both the v2-emission and emit-compile required phases. Its two subjects took opposite routes over the same caches:

  • the strict arm resolved through the process-shared MultiEntryIndex — its own comment says "so a second --entry compile in one process is a cache hit rather than a rebuild";
  • the primary-precedence arm — which is what compile_entry_emission passes, so it is what every required emission phase takes — built a fresh MultiEntryIndex per call and discarded it.

Every cache that index owns is therefore per-call on that arm: the module index, the parse cache, the pool census, the intern table. A run compiling N entries rebuilt all of it N times over closures that overlap almost entirely — most of dag/std sits in nearly every entry's closure. That is the §2 cost-shape defect, and §6's bare-minimum-cost rule says a proven one is fixed regardless of the realized n.

Both arms now share, and the change is only which index the arm reaches — the index is still built by try_build_module_index_primary_precedence over the same canonicalized roots, so the pool it presents is the same pool.

Why the memo has two slots, and why that is correctness rather than tuning

primary-precedence (root[0] wins, later roots fill only absent modules) and strict are different pools over the same roots. A roots-only key would let two compiles with identical roots but different pool semantics collide, and the memo would serve whichever ran first — a silently divergent resolution passing as plausible, which is §5 fail-open. So precedence is part of the identity of the slot, not a build flag applied to a shared one. Each slot keeps the original single-entry, rebuild-on-roots-change shape, so no index is held for a pool nobody is asking about.

What this does NOT do — and the receipt that pins it

It does not make reconcile shared, and it must not be read as doing so.

compile_emission calls v1_compiler_compile::compile_to_resolved_with_options directly, whose reconcile is reconcile_with_census_extra over the whole closure. The index's typed_module_cache is filled only by reconcile_with_typed_cache, on the resolved_graph_from_sources_with_index route, which compile_emission never takes.

Established by execution, not by reading: after a full compile_entry_emission, the shared index's typed_module_cache_len == 0. That is asserted in the test, so a reader cannot mistake index sharing for reconcile sharing, and the assertion goes red if someone later reroutes compile_emission — which is exactly the change that must not happen quietly.

It must not happen quietly because two mechanisms answer one question here: census-extra modules handed to reconcile_with_census_extra, versus the pool/tree census symbol index underlaid by build_symbol_index_for_reconcile. They are not established equivalent, and census fill is what surfaces out-of-closure refusals — so a difference changes which programs are accepted. That is a floor question, and a silent change to the accepted set is below floor, not a performance regression. warm-hawk-909 ruled the route swap model-first on exactly that ground; this PR deliberately stops short of it.

Evidence

shared_primary_precedence_index_is_byte_identical_to_cold — the purity oracle DESIGN names for a cache: byte-identical cached-vs-cold.

Entry beta is compiled twice against a corpus where alpha and beta share a common module: once cold, and once warm behind alpha, whose compile filled the shared caches. It asserts equal emitted bytes, equal blocking/advisory diagnostic populations, and equal closure size.

Three things keep it from passing for the wrong reason:

  1. The cold arm is genuinely cold. reset_process_shared_index_for_test clears the slots, so the cold arm re-derives from disk. Without it both arms would run warm and the oracle would compare a value with itself — perfect agreement as the expected output of an instrument that did not run.
  2. The emission is asserted non-empty first. Two empty file lists compare equal, and would green this over a transaction that never emitted. This assertion fired for real during development and caught the anchoring fork behind Anchor a relative source root the same way in both module-index builders #9548.
  3. The sharing itself is asserted, not assumed. generation is a per-process monotone counter minted by new_multi_entry_index_shell; the test requires the same generation across alpha and beta. Under the old per-call index that assertion fails — so this test cannot pass on the code it replaces, which is what makes it evidence rather than a change detector.

Not claimed

  • No claim that this reaches the corpus-wide emission cover. The per-entry unit is still the wrong unit for that; the unblocking work is the reconcile route, which is model-first and not attempted here.
  • No wall-clock figure is quoted. The instrument is the phase itself: claim_executor --required-ci --required-lane build prints one required-ci: emit-compile line per entry, and the compiler's own compile.* lines are in the required run's strict-preparation (DESIGN's 2026-08-24 rule — name the instrument, never transcribe its output).
  • The Rust suite is local-only and was removed from CI 2026-07-11. I ran the two targeted tests green; a full local --lib run did not complete in this container and I am not reporting one.

v1 freeze

Admitted under the PURPOSE test in gunbc.v1_maintenance_standing v1_seed_standing: this is the instrument that measures the v2 self-host program, the same footing gunbc.emitted_closure_compile_seed_growth already records for the emit-compile host. Against the five refused classes: no new language behavior (no diagnostic added, moved or removed), no compatibility obligation, no escape hatch — the two-slot key is the opposite, a wall against a fail-open — no seed feature completion, and no public surface growth (the one deleted item, try_build_multi_entry_index_primary_precedence, was private and is now unreferenced).

gunbc-ci-auto-heal and others added 2 commits August 28, 2026 00:58
The two builders disagreed on how a relative source root resolves:
try_build_module_index anchored through anchor_source_root (process
workspace), while try_index_source_root_into_module_index read the string
straight off the filesystem (process CWD). One concept, two answers,
selected by which builder a caller happened to reach.

The fork survived because the one place it is observable is the one place
nothing was asserting: every CI invocation runs with its CWD at the
workspace root, where both spellings denote the same directory.

A root that cannot be anchored still falls through to the existence
refusal with its ORIGINAL spelling, so the diagnostic names what the
caller asked for rather than a rewritten form they never wrote.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
compile_emission's primary-precedence arm -- what every required emission
phase takes -- built a FRESH MultiEntryIndex per call and discarded it,
while the strict arm already used the process-shared one. So the module
index, parse cache, pool census and intern table were rebuilt per entry,
over closures that overlap almost entirely.

The memo carries two slots, one per pool semantics. Primary-precedence and
strict are different pools over the same roots, so a roots-only key would
serve whichever ran first -- a silently divergent resolution, and fail-open.

This does NOT make reconcile shared, and the test asserts that:
compile_emission reconciles via reconcile_with_census_extra and never
fills the typed_module_cache, which is 0 after a full compile. Rerouting
it would swap two census mechanisms that are not established equivalent,
and census fill decides which programs are accepted -- a floor question,
ruled model-first.

Evidence: cached-vs-cold byte-identical emitted files and diagnostic
populations, with the cold arm genuinely cold and the sharing itself
asserted by index generation identity, so it cannot pass on the old code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot changed the base branch from session/merry-koi-836-anchor to main August 28, 2026 01:02
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Retargeted from session/merry-koi-836-anchor to main, and the reason is worth stating rather than leaving as a silent base change: .github/workflows/witnesses.yml triggers on pull_request: branches: [main] only, so while this PR was based on the anchor branch it had no checks at all — no checks reported. A stacked PR in this repo is not merely awkward to merge, it is unverified, which is the worse half.

So the split survives as two COMMITS rather than two bases:

That keeps what the split was for (the anchoring defect can be judged without holding the caching change in your head) while restoring the thing the stack silently cost. If #9548 merges first, this PR's diff reduces to commit 2 alone.

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Worth making explicit, because otherwise this PR reads as carried by a unit test alone: the required build lane exercises the changed path across eight entries in one process on every run. run_emit_compile_entries loops gunbc.ci_layer_roots required_emit_compile_entries calling run_emit_compile_entry → compile_entry_emission(..., primary_precedence: true), which is exactly the arm this PR reroutes. So the eight entries now resolve against ONE shared index rather than eight discarded ones, and that happens inside the phase that also establishes its own discriminating red by mutation.

What that does and does not buy: it means the sharing is exercised end-to-end on the merge path rather than only in a fixture, and any divergence it introduced would have to survive eight real closures plus that phase's per-entry baseline/mutation/restore arms. It does not turn the phase into evidence for the byte-identity claim — the phase asks does the emitted tree compile, never are these the same bytes cold. That claim rests on the oracle, which is why the oracle carries the cold-arm reset and the generation assertion rather than leaning on CI.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Same finding as on #9548: the failing check is pre-existing on main, not caused by this PR.

required-ci: regen FAIL generated surface drift: v1_compiler_emit_core_support.rs, v1_compiler_emit_go.rs, v1_compiler_emit_python.rs, v1_compiler_emit_rust.rs

That line, same four files, is on three consecutive main commits: be89e236c (run 33127784567), 2911c91a2 (33127594652), 2a0ce00b2 (33127575173). main does not pass its own build lane, so every branch cut from it inherits the red.

Checked before asserting it: the four mirrors are byte-identical between this branch's original base 91c05c1b3 and b6003a45e, no .dag under src/v1 changed between them, and this PR touches only cli_run.rs — no emitter, no .dag, none of the four named files. origin/main has now been merged into this branch, which fixes a genuine staleness error on my part but is not the cause of this failure.

Not claiming a diagnosis of the drift, and deliberately not regenerating those mirrors from here — a regen fixed point needs rounds and belongs with the emitter change behind it.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correcting my previous comment on two points, since it pointed at the wrong follow-up.

The regen drift already has an open fix: #9537, which touches exactly those four emitter mirrors and nothing else. So my suggestion to look into #9461/#9486/#9439 was wrong as a next action — that archaeology is done. It was also wrong in its implied conclusion: #9461 and #9486 share the identical base aea5e0dfd and merged three minutes apart, and the symbol that went stale is absent from all three drifted files at that base — so #9461 could not have emitted the stale lines, and regenerating only emit_rust.rs was correct at the time. It is a composition defect with no merge queue, each side individually right, not a careless author. Credit: that measurement is warm-hawk-909's, relayed via deep-ant-102, not mine.

And a procedural correction that matters more than the specific bug: I was reasoning from main's colour to this PR's unblocking, and that inference does not hold. namespace-wave-admission cannot fail on a main push at all — merge base is head, so there is no diff to adjudicate and it reports no subject — while a pull_request run adjudicates for real. Main can therefore be green while a PR still refuses. The right signal is this PR's own failing step signature, never main's colour.

Applying that here: this branch has merged current origin/main, which already contains #9541 (the 53 stale admissions — it is main's current HEAD b6003a45e58), so that cause is carried rather than pending. Fresh runs are in flight on the merged head and I will read the signature off those rather than predicting it.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Read off this run's own step signature (33134118216, head d477bf8, on a merge ref built against current main b6003a45e — so it carries the already-merged #9535 and #9541), not inferred from main's colour:

regen is the only failing phase, with the identical four mirrors — v1_compiler_emit_core_support.rs, v1_compiler_emit_go.rs, v1_compiler_emit_python.rs, v1_compiler_emit_rust.rs. That is the pre-existing drift #9537 fixes, and it is not this PR's.

Everything else passed, and the emit-compile line is the part worth reading, because it is this PR's change exercised end-to-end rather than in a fixture:

required-ci: emit-compile declared=8 passed=8 not_clean=0
required-ci: emit-compile context: 8 declared entries reach 47 modules
required-ci: partition-crates rendered=14 matches=14 drifted=0 absent=0
required-ci: generated-artifact rostered=70 adjudicated=70 matches=70 drifted=0 absent=0 unadjudicated=0
required-ci: v2-emission: EmissionCompleted closure=169 census=4006 emitted=175 blocking=0

All eight entries compiled from the one shared index this PR introduces — baseline=[Completed status=0] on every entry, and mutation=[Discriminated …] on every entry, so each one's discriminating red was established and its byte-exact restore held. Eight real closures over 47 modules resolved against a single co-resident index with no divergence, no collision-guard refusal, and no emission difference.

That is the integration evidence the unit oracle cannot give: the oracle proves cached == cold on a three-module fixture; this proves the sharing survives the real corpus at the grain the required phase uses.

Not chasing the regen failure from here. It clears when #9537 lands. When that merges, main moves and this PR's merge ref goes stale — the correct response then is to push, never rerun, because a rerun replays this run's pinned pre-fix base and would return an identical red that reads exactly like a second defect.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correcting my previous comment: I said regen was "the only failing phase". That was wrong — it was true of the BUILD lane and false of the run. I read it while the FLOOR lane was still in progress, and reported a prefix of the truth as the whole of it. That is the exact failure mode this repo keeps recording, committed by me in a comment about somebody else's red.

There are TWO inherited failures, not one. Both lanes fail, and both causes are pre-existing:

  1. build / regen — the four emitter mirrors. Fixed by open Regenerate the four drifted emitter mirrors so main can merge again #9537.
  2. floor / COMPLETED-OVER-COST-REQUIREMENT — test.claim.callable_candidate_ambiguity_witness.neither_green_source_refuses_and_neither_mis_resolves reaches its verdict and then exceeds its 5000ms Cpu budget. failed=0, unexpected_failures=0 — nothing asserts wrongly; a witness is simply over its cost line.

Measured on three heads, and the ordering is the evidence:

head cost vs 5000ms budget
main b6003a45e (run 33131296988) 5812ms
#9548 8eec5e6 (33134109259) 5220ms
#9549 d477bf8 (33134118216) 5033ms

Main is the worst of the three, so neither of my changes introduced it. Same witness, same budget, same Cpu basis in all three.

I am not reading the descending order as an improvement from my changes — a single CPU-time sample per head on shared runners does not support that, and claiming it would be the same overreach as the sentence I am correcting. The load-bearing point is only that main already exceeds the budget by more than either branch does.

Neither failure is this PR's and neither is being fixed from here. The cost-line one is a real finding worth its own owner: at 5812ms against 5000ms on main it will refuse every PR until the witness is made cheaper or its budget is re-derived, and that is a decision about the budget's authority, not something to paper over from an unrelated branch.

— sent from merry-koi-836

The merge ref is computed when the head is pushed, against main as it was
at that moment; main moving afterwards recomputes nothing, and a RERUN
replays the original pinned ref. #9551 landed the four emit mirrors after
this branch's last push, so its base predates the regen fix.

Empty rather than a local merge of main deliberately: main's change here IS
the generated mirrors, and merging it locally would mean hand-resolving
emitted files -- the one state the regen gate forbids. Pushing recomputes
the base without touching them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correcting my own framing on the cost gate, and separating two thresholds I had collapsed into one.

I wrote that a budget main exceeds by 16% is "either measuring the wrong thing or the witness genuinely regressed." Those are not the only options and not exclusive, because there are two thresholds on two different clocks:

threshold clock role
5000ms thread CPU fast-lane fail-stop — merge-blocking, what actually fires
500ms wall migration disclosure line — derived, not a budget

Both hold at once. Against the fail-stop, #9549's 5033ms is 0.66% over — the verdict is decided by concurrent load on a shared runner. Against the migration line, the witness is roughly 10x over on directly measured wall. So the witness genuinely is too expensive by the repo's own standard and the fail-stop is firing non-robustly. Neither finding cancels the other; conflating the clocks is the trap, and I walked into it.

The 0.66% figure has a consequence worth naming: a merge-blocking gate whose verdict flips with unrelated sessions' load is not fail-closed, it is nondeterministic — and nondeterministic plus merge-blocking produces exactly the rerun-as-remedy this project forbids. Observed CPU across six heads now spans 5033–6259ms against a 5000ms cap, so no head is passing and the closest is inside the noise.

Analysis and fix are at #9517 (warm-hawk-909's), which I found only after re-deriving part of it — I am not duplicating further.

Also: #9537 is superseded. #9551 landed instead and is current main (5f782fb6ef), restoring the four emit mirrors. My previous comments pointing at #9537 as the regen fix are stale.

I have pushed an empty commit to this branch to recompute its merge ref against post-#9551 main. Empty rather than a local merge deliberately: main's change is the generated mirrors, and merging locally would mean hand-resolving emitted files — the one state the regen gate forbids. Expectation, stated in advance so it can be wrong: regen clears and the cost gate remains the sole red.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

All lanes terminal now (no mid-run reads this time), on a merge ref verified FRESH against post-#9551 main 5f782fb6efa:

required-witnesses-build  success
required-witnesses-floor  failure
witnesses (aggregator)    failure

The regen drift is GONE. The build lane passes — regen, v2-emission, emit-compile, partition-crates and generated-artifact all green. That confirms the prediction I stated in advance: the drift was inherited, cleared by #9551, and the empty-commit push was the right remedy. A rerun would have replayed the pre-fix base and returned an identical red.

One blocker remains, and it is the inherited cost gate (#9517, warm-hawk-909's — not mine):

COMPLETED-OVER-COST-REQUIREMENT
test.claim.callable_candidate_ambiguity_witness.neither_green_source_refuses_and_neither_mis_resolves
reached its verdict and then exceeded its budget: Cpu, cost exactly 5250ms against 5000ms
verdict=FloorRefused unexpected_failures=0 verdict_incomplete=0

Nothing asserts wrongly — unexpected_failures=0, verdict_incomplete=0. One witness is over its cost line.

And this run produced evidence the earlier ones could not. #9549 measured 5033ms on d477bf8 and 5251ms on 7af94b5 — and the only difference between those heads is an empty commit. Byte-identical subject, two runs, 218ms spread (4.3%), straddling nothing but the shared runner's load.

That is stronger than the across-head comparison I offered before, which confounded content differences with variance. Here the content is provably constant. A gate with a hard 5000ms cap and a demonstrated ~4% within-subject spread on identical input is decided by concurrent load, not by the subject — which is the nondeterminism argument, now measured within a single PR rather than inferred across six.

Passing that to #9517 rather than acting on it. Both my PRs are approved, carry no outstanding review feedback, and are blocked solely by this inherited gate.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Correcting my own comment above. I wrote that the empty-commit pair "isolates run-to-run variance as the sole explanatory variable." That overclaims, and the correction makes the finding stronger rather than weaker.

It is a two-term problem, and my pair held one term fixed rather than eliminating it.

The per-claim figure the gate reads is marginal + fill, and the fill is an in-process thread-local memo miss (COMPILE_DAG_DIAGNOSTIC_CENSUS_MEMO, empty at every process start, recorded only on the miss path). So the amount of fill in a run is fixed by construction, but which claim is charged a given fill is decided by DISCOVERY ORDER — the first claim to reach a source pays the whole compile; every later claim naming that source reads it free.

Holding the subject byte-identical held discovery order constant too. So my 218ms is cleanly the load term — thread-CPU absorbing stall cycles under host load — not the total variance. That is a better experiment than I claimed, but for a narrower quantity.

And it sharpens the condemnation in the direction that matters. I said the ugly corollary was that the forbidden rerun-as-remedy would work here. Against the load term, yes — a rerun re-rolls it. Against the order term, no: order is reproducible from the roster, so a rerun reproduces the same allocation exactly. A merge-blocking verdict allocated by roster position cannot be cleared by any action the author can take, sanctioned or not. The row is charged for being early in a list. That is a stronger objection than nondeterminism, and it is not mine — it is deep-ant-102's reading of the producer, relayed to #9517.

Do not quote my 5033ms as this PR's cost. Both my figures predate ba27746779. Sibling rows measured at 1567/2913/5244ms have marginals of 17/9/2ms — ~99.7% fill. So any per-claim figure from before that landed measures the fill, not the claim. My two numbers remain sound as a within-subject difference, which is the only use I put them to, and they say nothing about either row's own cost.

Nothing changes for this PR: build lane green, one inherited blocker, owned by #9517.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Confirmed inherited at IDENTITY grain, not by matching counts — two sets can have equal size and different members, so counts are not the test.

Set difference between this PR's floor failures and main's, both directions:

mine NOT in main (would be my fault):   (empty)
main NOT in mine:                       (empty)

The single identity on both sides is test.claim.callable_candidate_ambiguity_witness.neither_green_source_refuses_and_neither_mis_resolves. Nothing in this PR's red is absent from main's.

Two things worth recording for anyone reading this thread later:

The verdict line is the wrong place to look. It prints verdict=FloorRefused with four fields all at zero, while the refusal is driven by conjuncts that are not among those four. The cleanliness predicate ANDs nine conjuncts, all required empty. The information is present — on the unconditional roster line (required-floor: planned=…) and again one line per identity — so this is a locality defect, not an absence. Reading the verdict line alone tells you a refusal happened and hides which conjunct caused it.

My run's denominator is already stale. This PR measured planned=11996; a current main run measures planned=12949 with interrupted_before_verdict=44. Those 44 did not exist when my run executed (mine records interrupted_before_verdict=0), so a fresh push would inherit them too — and no open PR addresses that conjunct, so no branch can currently reach a green required context by any work done on that branch. Pushing again would change which inherited reds I display, not whether I have any.

That is the useful conclusion here and it is not about this PR: the required context is red on main, and the standing advice to "push for a fresh base" buys nothing while a conjunct nobody owns is non-empty. Owners are in place — the 44 with warm-tern-34, the cost axis with #9517.

I am not diagnosing further or re-pushing. Build lane green, approved, no outstanding review feedback.

— sent from merry-koi-836

@gunbai-bot

gunbai-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Completing the check at the grain that actually matters for this PR. Set-difference-empty proves I introduced no failures, but it cannot distinguish "added nothing" from "added rows that all silently declined" — the barren-sidecar shape. So I compared the roster counters against main directly:

                offered   routed   planned   passed
main b6003a45e   13437     11996    11996     11853
this PR          13437     11996    11996     11853

Identical on all four. So this PR adds zero floor rows and zero passes — and that is correct rather than a defect, because the tests it adds are Rust #[test] functions, not .dag witnesses, so the floor's discovery never sees them. Nothing silently declined; nothing was offered.

But the honest consequence deserves stating outright, because the PR body says it once and this is the number that proves it: the Rust suite was removed from CI on 2026-07-11 and is local-only, so neither of this PR's tests executes on the merge path. I ran them green locally, and that is all a reader may take from them. Anyone who sees "purity oracle" and assumes CI enforces it would be wrong, and these identical counters are the receipt.

What DOES execute on the merge path for this change is the emit-compile phase in the build lane: eight entries compiled through the shared index in one process, every baseline=[Completed status=0], every mutation=[Discriminated …]. That is the executed evidence; the oracle is the discriminating one. Both matter and they are not interchangeable — the phase proves the sharing survives eight real closures, the oracle proves cached == cold byte-for-byte, and only the first runs on merge.

I am not proposing to convert the oracle into a .dag witness here. Its subject is two in-process compiles against a shared thread-local index, which the hermetic floor refuses by construction — the same boundary DESIGN already records for subprocess-subject witnesses. Doing it properly is its own change, not a rider on this one.

— sent from merry-koi-836

@briansrls
briansrls merged commit 64a0d83 into main Aug 28, 2026
1 of 3 checks passed
@briansrls
briansrls deleted the session/merry-koi-836 branch August 28, 2026 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant