Skip to content

feat: support Cursor as a primary harness - #28

Merged
Quidge merged 8 commits into
mainfrom
fm/cursor-parity-sync
Aug 14, 2026
Merged

Quidge merged 8 commits into
mainfrom
fm/cursor-parity-sync

Conversation

@Quidge

@Quidge Quidge commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Intent

Reconcile the fork (Quidge/firstmate = origin/main) with upstream (kunchenguid/firstmate
= upstream/main): sync in the 6 upstream-only commits via a merge commit, adopt
Cursor-as-primary, and DROP the fork's Cursor attribution guard entirely. This is
firstmate's OWN shared tracked material, so firstmate-coding-guidelines applies.

STEP 1 - Sync merge, preserving upstream SHAs.
On branch fm/cursor-parity-sync, git merge --no-ff upstream/main brings in exactly six
upstream-only commits: 96876db (quota floor), 85cefa9 (Pi watcher-handoff), 81f7020
(Cursor-primary), 5521323 (decision-hold decline/repair), db0280f (buried wake-status),
88d0f2e (max Calm). Upstream SHAs MUST be preserved - never rebase, squash, or
cherry-pick. The --no-ff merge commit is what preserves them and must stay intact through
the whole pipeline. If any pipeline mechanic would rewrite that merge history, stop rather
than proceeding.

STEP 2 - Resolve merge conflicts (two files).

  • bin/fm-spawn.sh: TAKE UPSTREAM's version. Verified first that the ONLY fork-local
    divergence in this file since the merge base was the attribution guard (3 hunks: header
    comment, hook creation, hook activation), so taking upstream drops only the guard.
    The result is byte-identical to upstream/main:bin/fm-spawn.sh.
  • docs/architecture.md: PRESERVE BOTH. The fork's Option-A supervision-policy
    documentation (0b138d9) is kept verbatim, with upstream's Cursor-primary clause folded
    into the same primary-harness list.
    Every other dual-touched file was semantically reviewed, not trusted to auto-merge:
    .agents/skills/harness-adapters/SKILL.md, AGENTS.md, README.md, bin/fm-session-lock-lib.sh,
    bin/fm-teardown.sh, bin/fm-wake-lib.sh, docs/verification/runtime-backends.md,
    docs/watcher-continuity.md.

STEP 3 - Fully remove the Cursor attribution guard.
Taking upstream's fm-spawn.sh removes the guard's install; the remaining wiring is removed
in a follow-up commit stacked after the merge:

  • bin/fm-teardown.sh: remove remove_cursor_artifacts and both call sites (it existed only
    to delete state/.cursor-git-hooks; the separate .cursor-session cleanup is untouched).
  • tests/fm-cursor-harness.test.sh: remove section 2b (guard-only) and its single-caller
    spawn fakebin helper.
  • .agents/skills/harness-adapters/SKILL.md and docs/verification/runtime-backends.md:
    remove the paragraphs describing the hook as current behavior, reconciled against
    upstream's rewritten Cursor section. The fork-local probe-transcript pointer survives.
    Acceptance: git grep for cursor-git-hooks, @cursor.com, @cursor.sh, core.hooksPath, and
    remove_cursor_artifacts must all be empty, with no dangling reference to the removed hook
    script or tests.

STEP 4 - KEEP untouched (do NOT revert or remove).

  • Option-A supervision policy (42f134e / 0b138d9) in bin/fm-wake-lib.sh, bin/fm-watch.sh,
    bin/fm-watch-arm.sh, bin/fm-push-transition-lib.sh, docs/architecture.md,
    docs/watcher-continuity.md. Upstream's 85cefa9/db0280f must NOT revert it to upstream's
    louder-failure verdict; the attach-only benign stand-down must survive.
  • 864dcda cursor-like-filename reject fix in bin/fm-harness.sh. Do NOT restore permissive
    cursor-agent filename matching even if an adjacent identity file conflicts.
  • 40226a9 Context7 MCP registration (.mcp.json), de43bc7 devtools-leak evidence doc, and
    all 8 general fork skills (lavish, aside, rebasing-adapted-skill, writing-for-agents,
    tailscale-serve, etc.). These stay as intentional fork divergence; NOT upstreamed.

STEP 5 - Adopt Cursor-as-primary (arrives with 81f7020).
No extra work beyond a clean merge. These files must be present:
.cursor/hooks.json, bin/fm-turnend-guard-cursor.sh, bin/fm-sessionstart-cursor.sh,
bin/fm-hook-host-lib.sh, docs/supervision-protocols/cursor.md,
tests/fm-cursor-primary.test.sh, tests/fm-cursor-primary-live-e2e.test.sh.
The Cursor --secondmate refusals in bin/fm-spawn.sh, bin/fm-control-lib.sh, and
bin/fm-remote-secondmate-control.sh must be lifted (only muse remains refused).

IN-SCOPE CORRECTION beyond the guard.
tests/fm-cursor-harness.test.sh's header claimed Cursor "is a crewmate/scout adapter only
and refuses a secondmate launch". Upstream never updated that comment when kunchenguid#2305 lifted the
refusal, and it has no backing assertion, so it directly contradicts Step 5's acceptance
criterion. Corrected rather than carried in.

ACCEPTED CONSEQUENCE of dropping the guard.
Cursor-authored commits can again carry Co-authored-by: Cursor <cursoragent@cursor.com>,
which AGENTS.md forbids. Upstream implements no equivalent protection. This is the
captain's explicit decision, so the guard is removed cleanly rather than half-wired, and no
replacement policy documentation was invented. If this surfaces as an ask-user finding it
must be escalated to firstmate, not answered by the worker.

VALIDATION EXPECTATIONS.
The full portable regression set runs in the pipeline, including the new
tests/fm-cursor-primary.test.sh and the updated secondmate/session-lock/turn-end/pretool
tests. The opt-in live Cursor-primary smoke
(FM_CURSOR_PRIMARY_LIVE_E2E=1 bin/fm-test-run.sh tests/fm-cursor-primary-live-e2e.test.sh)
is run where feasible but is NOT a separate gating eval; the captain trusts upstream's
testing and does not want a throwaway-home evaluation gating the land.

LIVE CURSOR-PRIMARY SMOKE: RUN AND FULLY PASSED on this host (not a gating eval).
FM_CURSOR_PRIMARY_LIVE_E2E=1 bin/fm-test-run.sh tests/fm-cursor-primary-live-e2e.test.sh
against real cursor-agent 2026.08.11-e8db854: 7 of 7 cases passed, failed=0. Covered the
session lock taken by the Cursor process itself, run-tier session start completing every
stage, sessionStart additional_context reaching model context before the first turn, the
stop-hook park delivering a real watcher wake as one follow-up, the park owning exactly one
arm cycle with a live watcher beacon, the supersession baton standing an older park down
after the next stop claim, and away-mode escalation delivery being confirmed and processed.

PORTABLE SUITE RESULT: 147 scripts, 4 failed, 32 gate-skipped. One of those four
(tests/fm-tmux-agent-liveness.test.sh) exposed the real merge defect fixed above; the
remaining three are accounted for below.

tests/fm-watcher-lock.test.sh fails on "arm did not exit with HUP status (got 124)". This
file sits in the Option-A / upstream-watcher overlap zone, so it was NOT assumed
environmental; it was settled with the same differential used for Calm, run strictly
serially because concurrent load was the first hypothesis. Three runs per tree:

HEAD (merged) -> fails 3/3
origin/main -> fails 3/3 (fork main, no upstream merge)
upstream/main -> fails 3/3 (upstream alone, no fork content)

It fails identically and deterministically on BOTH unmerged parents, so it is not a merge
regression. Root cause is the same uutils-coreutils host issue: /usr/bin/timeout is uutils
coreutils 0.8.0, and 124 is timeout's own timed-out exit code, where the assertion expects a
signal-derived HUP status (GNU timeout reports 128+signal). The Option-A cases themselves -
the benign attach-only stand-down and the owning arm's typed failure - pass.

Correction to an earlier note: a single standalone run of this test reported failed=0, and
that observation did not reproduce; the controlled 9-run differential above supersedes it.
The regression question is answered by the differential, not by that one pass.

KNOWN ENVIRONMENTAL FAILURES ON THIS HOST - do NOT chase, do NOT "fix" here.

  1. tests/fm-cursor-primary.test.sh hard-fails with "a C compiler is required to build the
    fake Cursor process". This host has no cc/gcc/clang. It is upstream's harness-dependent
    structural-identity test and runs normally on CI's ubuntu-latest/macos-latest runners,
    which ship compilers. Not a code defect and not a regression from this change.
  2. tests/fm-calm-pi-extension.test.sh fails the case "Pi follow-up loaded_on case rendered
    a duplicate captain answer". Verified pre-existing and NOT merge-induced: exporting each
    parent tree with git archive into a clean temp dir and running the test there fails
    identically on origin/main alone (no upstream merge) and on upstream/main alone (no fork
    content). Upstream's own new max-Calm case passes here. The fork's only Calm divergence
    since the merge base is a single mock stub (getMarkdownTransformers) in the test file.
  3. tests/fm-tmux-agent-liveness.test.sh is a known local failure on this uutils-coreutils
    host (tracked fork issue, unrelated to this change): /usr/bin/sleep is a symlink into
    the uutils multicall binary, so any fixture symlink named cursor-agent exits immediately
    with "coreutils: unknown program 'cursor-agent'" and its pane never renders. Unmerged
    upstream/main fails on this host the same way, at its first symlink fixture. Do not
    chase or "fix" that here.
  4. tests/fm-watcher-lock.test.sh fails on "arm did not exit with HUP status (got 124)", the
    second uutils manifestation: /usr/bin/timeout is uutils coreutils 0.8.0 and 124 is its own
    timed-out exit code where the assertion expects a signal-derived HUP status (GNU timeout
    reports 128+signal). Settled by the serial 3-runs-per-tree differential recorded above:
    fails 3/3 on HEAD, 3/3 on origin/main, and 3/3 on upstream/main, so it is deterministic on
    both unmerged parents and not a merge regression. The Option-A cases pass.
    The suite in general may need TMPDIR on a large disk.

These four are proven environmental on this host, each by differential rather than
assumption. If the test gate flags any of them, they must NOT be "fixed" here and must NOT be
force-passed: present this evidence and escalate as a decision instead.

REAL MERGE DEFECT FOUND AND FIXED in tests/fm-tmux-agent-liveness.test.sh (NOT environmental).
Separately from the uutils issue above, the auto-merge put two fixture strategies on one
path. The fork's make_runner already creates $LAB/bin/cursor-agent as an exec -a wrapper;
upstream's new Cursor composer cases then ran ln -s "$SLEEP_BIN" "$LAB/bin/cursor-agent"
over it. ln refuses an existing path on every platform, so upstream's symlink was never
created and its positive case silently asserted against the wrapper, which can never
classify as Cursor (exec -a leaves comm as the real binary's name and puts the fixture path
only in argv[0], while fm_tmux_pane_is_cursor reads comm, which only a symlink populates).
This reaches CI, where the symlink would otherwise work. Fixed by moving the symlink
fixtures to their own directory and pointing the three composer cases at them, leaving the
alive-set case on the wrapper it needs. This is exactly the "auto-merge is not
semantic-merge" review the task required, and it does not weaken 864dcda, whose change was
scoped to detect_own() in bin/fm-harness.sh and not to the tmux pane classifier.

DELIVERY.
One sync+reconciliation PR into Quidge/firstmate main via the no-mistakes pipeline. The
captain is the merge authority (yolo off); the worker never merges.

What Changed

  • Add Cursor as a primary and secondmate harness with session-start, pre-tool, turn-end watcher, and tmux composer integrations.
  • Add decision-hold decline and repair paths, unread wake-status delivery, Pi watcher handoff handling, quota version enforcement, and max Calm presentation.
  • Remove the fork-specific Cursor attribution hook and update Cursor documentation and regression fixtures accordingly.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed
✅ **Rebase** - passed
✅ **Review** - completed
⚠️ **Test** - 2 warnings
✅ **Document** - passed
✅ **Lint** - passed
✅ **Push** - passed

kunchenguid and others added 8 commits August 13, 2026 00:36
* fix: raise quota-axi floor to 0.1.25 for Cursor CLI quota awareness

Homes on latest main need quota-axi kunchenguid#87 so Desktop-absent CLI machines report a fresh Cursor quota instead of a false sign-in-required.

* no-mistakes(document): Update quota floor documentation pointer
…id#2304)

* fix(guard): stop the false send-time watcher-down alarm on Pi primaries

On a Pi primary the watcher process is not the liveness signal. The Pi
extension tears the watcher down on every actionable wake and spawns the
replacement itself, so the singleton lock is legitimately unheld between
cycles: every one of the 799 cycles in a live primary's ledger ends with
lock_after=pid:none, and a live capture caught the guard verdict flipping to
no-watcher during one hand-off with the beacon 63s old.

bin/fm-guard.sh classified Pi as a persistent-watcher harness, which demands a
live identity-matched lock holder at all times, so any guarded command landing
in a hand-off painted the full WATCHER DOWN - SUPERVISION IS OFF banner and
told firstmate to repair a cycle the extension already owns and is restoring.

Add an extension supervision model for pi and pi-signed. A live
identity-matched watcher stays the ordinary healthy state; an unheld lock is
healthy only while the beacon is fresh within grace AND a live Pi session
provably owns continuity - both primary extensions recorded in their state
markers at their current on-disk builds by the process named in state/.lock,
with that process still alive. Without that proof the banner fires exactly as
before, so an unloaded, version-drifted, or exited Pi session is loud
immediately and a cycle the extension never restores is loud once the beacon
passes grace. The queued-wake warning, the PID-strict turn-end guard, and
every other primary's detection are untouched.

Fold session-start's duplicate Pi marker predicate into the shared library so
the ownership contract has one owner.

* no-mistakes(review): Restrict Pi hand-off tolerance to unheld watcher locks

* no-mistakes(document): Document Pi watcher hand-off supervision
* feat(cursor): add Cursor Agent CLI primary hooks, park supervision, and session start

Register a tracked project-scope .cursor/hooks.json for Cursor's stop,
sessionStart, preCompact, and preToolUse steps.

bin/fm-turnend-guard-cursor.sh owns Cursor's turn boundary as a park: it
foregrounds the watcher arm, holds the boundary open until an actionable close,
and returns that wake as one follow-up. Exit 2 is a silent no-op on Cursor's
stop step, so the adapter never uses it. The follow-up loop is bounded twice,
by Cursor's own loop_limit and by the payload's loop_count.

bin/fm-sessionstart-cursor.sh delivers the digest as additional_context at
sessionStart, and stages it for the next turn boundary at preCompact, which
cannot inject context.

Cursor also loads the tracked Claude settings, so bin/fm-hook-host-lib.sh lets
each tracked Claude-shaped entrypoint stand down on a Cursor-delivered payload
rather than running every covered event twice.

bin/fm-tmux-lib.sh reclassifies a Cursor pane's composer cursorlessly, because
Cursor parks its terminal cursor outside the composer, which restores a genuine
composer-empty proof and unblocks away-mode escalation delivery.

* feat(cursor): make Cursor Agent CLI a verified primary harness

Resolve Cursor in the session-lock ancestry through bin/fm-cursor-lib.sh, which
a Cursor primary needs before it can hold its own home lock, and classify its
stop-hook park under the autoarm supervision model so the mid-turn pull guard
stops reporting a healthy between-turns watcher as down.

Read a Cursor pane's composer cursorlessly on tmux, gated on Cursor's own
structural process identity, which restores a genuine composer-empty proof and
lets away-mode escalations reach a Cursor primary with no daemon change.

Lift the secondmate refusals in bin/fm-spawn.sh and bin/fm-control-lib.sh now
that the supervision protocol exists and is recorded.

Cover the whole surface with a portable regression over real processes, an
opt-in live guard against the installed cursor-agent, and dated per-harness
evidence.

* docs(cursor): record Cursor as a verified primary across the owning surfaces

Update the turn-end guard, session-start, arm-seatbelt, cd-guard, watcher
continuity, architecture, configuration, README, and harness-adapters owners,
and add dated live evidence to the supervision and runtime-backend verification
records. Correct the recorded Cursor tmux composer verdict: the cursor-anchored
read is still blind, but the composite reader is no longer unknown.

Lift the remaining remote-secondmate refusal missed in the previous commit, and
add the new libs to the existing fixtures that copy a fixed dependency list.

* refactor(cursor): name the park's stand-down condition for both its causes

Also record that Cursor's preCompact firing itself is not yet live-verified,
while the static evidence that it cannot inject context, and the staging path
that follows from it, both are.

* test: give the pretool fixtures their new dependency and one lint owner

The cd-guard fixture copies a fixed dependency list and now needs the shared
hook-host predicate. Both pretool suites also asserted cleanliness with a bare
shellcheck call, a second and weaker copy of the lint definition that
bin/fm-lint.sh owns: it omits --external-sources, so it failed the moment these
checkers sourced a shared library. They now delegate to that owner.

* test: assert the cursor secondmate contract instead of its removed refusal

A cursor secondmate now launches, so the suite asserts what its park actually
needs: --trust so the home's project hooks load at all, its own home pinned as
the workspace, and the autoarm supervision model inherited across the launch.

* no-mistakes(review): Serialize Cursor wakes and bind staged context

* no-mistakes(review): Serialize Cursor context and nag state commits

* no-mistakes(review): Enforce Cursor ceiling before staged context delivery

* no-mistakes(review): Serialize Cursor claims and staged context

* no-mistakes(review): Serialize Cursor ownership and state commits

* no-mistakes(review): Protect Cursor context across session takeover

* no-mistakes(review): Preserve Cursor context across session takeover

* no-mistakes(review): Enforce owner-keyed Cursor staged context

* no-mistakes(review): Atomically claim Cursor follow-ups and staged context

* no-mistakes(review): Defer Cursor preCompact staging and simplify supersession

* no-mistakes(review): Serialize Cursor park commits and defer preCompact

* no-mistakes(review): Stop Cursor parks after session takeover

* no-mistakes(test): Route Cursor preCompact context through stop follow-up

* no-mistakes(document): Update Cursor primary documentation

* revert(cursor): cut preCompact staging from this change

Carrying a compaction digest across two concurrently running stop hooks kept
producing races that could deliver it twice or strand it indefinitely, and
closing them kept enlarging a critical section inside a hook Cursor awaits at
the turn boundary. Native preCompact firing was never observed either, so the
surface has no empirical basis yet.

Remove the adapter, its registration, its staged path in the park, and its
tests, and record the surface as deferred and uncovered alongside the Codex
interactive TUI. A regression now asserts preCompact stays unregistered so it
cannot return without its own design and evidence.

This change ships the proven core only: the turn-end follow-up park, the
run-tier session start, and away-mode delivery.

* no-mistakes(review): Correct Cursor park supersession documentation

* no-mistakes(document): Clarify Cursor run-tier verification ownership

* no-mistakes: apply CI fixes

* no-mistakes: apply CI fixes

---------

Co-authored-by: kunchenguid <kun-1@kunchenguid.com>
…id#2330)

* feat(bin): add unrouted close paths to the captain decision gate

A captain who declines a held decision leaves no follow-up work to route,
so `resolve` could not express that answer: it requires at least one
`--routed-to` task. The only way to close such a hold was a direct
`tasks-axi done`, which never writes the durable resolution record the
completion gate reads, so the originating investigation could no longer
pass `verify` and its cleanup stayed blocked.

Add two close paths that route no work:

- `decline` closes an actively held hold with a recorded captain decision
  and no routed task. It refuses while any task is still blocked by the
  hold, because releasing routed work without recording it is `resolve`'s
  job.
- `repair` records the missing resolution block on a hold that was already
  closed outside this script. It never reopens a hold and never clears a
  dependency edge, and it refuses a hold that is still actively held.

Both require a non-empty captain decision file and share `resolve`'s
digest-based retry identity, so an exact retry is idempotent while a
changed decision is rejected. The recorded body now also names which path
closed the hold, and each routed entry regains its own line.

The gate itself is unchanged: an unanswered decision still fails
completion and blocks teardown, and neither new path can close a hold
without the captain's recorded word.

* fix(bin): require captain-hold provenance before repairing a decision

`repair` checked only that the backlog item was kind captain and Done, so
an ordinary captain-kind task that was never held for the captain could be
closed, repaired, and then pass the completion gate.

tasks-axi keeps `hold_kind` through a close, so it is the surviving proof
that an identity really was a captain hold. Require it before writing the
resolution record, and cover the case in the gate regression.

* no-mistakes(document): Correct decision-hold lifecycle documentation
* fix(bin): surface buried status notes on wake drain

A note: answer immediately followed by a routine note was dropped because
annotations kept only the newest line and note: never enters OPEN DECISIONS.
Present every unread note and pending-reply resolution since the last drain
cursor, and annotate every unread line on a queued signal.

* no-mistakes(review): Fix unread status cursor races and overflow

* no-mistakes(review): Preserve cursors when status span reads fail

* no-mistakes(review): Make status presentation transactional under I/O failures

* no-mistakes(review): Simplify unread status cursor and presentation locking

* no-mistakes(review): Align cursor failure regressions with transactional presentation

* no-mistakes(review): Retire stale presentation cursors during task teardown

* no-mistakes(review): Preserve routine status until signal annotation

* no-mistakes(review): Correct unread status cap documentation

* no-mistakes(document): Document unread wake status presentation

* no-mistakes(lint): Fix wake surfacing ShellCheck warnings

* no-mistakes: apply CI fixes
* feat(calm): add a max presentation level that hides mid-turn working notes

Calm's home-local preference becomes a three-state level instead of a
boolean: "off" is stock Pi, "on" is today's Calm, and "max" is Calm plus
hiding the assistant text of messages the model did not end its response
with. `/calm max` selects it from any state, a plain `/calm` steps max
back to ordinary Calm and otherwise keeps the existing on/off cycle, and
any other argument keeps that cycle too.

`config/calm` now persists "max" as its own literal value, so a session
start, resume, fork, or reload restores the stored level rather than
treating it as unrecognized and dropping to off.

The hide rule keys on Pi's intrinsic per-message stopReason: "toolUse",
or "length" with tool calls present. Streaming ("pending") text is never
filtered, because suppressing it would also stop a genuine reply from
streaming. The existing assistant layout adapter filters the blocks out
of the same shallow presentation copy it already uses for collapsed
thinking, so the message, model context, session storage, /export, and
delivery are untouched and a hidden mid-turn row collapses to zero
height. The new "assistant-working-note" class keeps that choice in the
visibility policy owner, where ordinary Calm keeps it visible.

* no-mistakes(document): Clarify Calm max persistence and taxonomy
… attribution guard

Brings in the six upstream-only commits since the 4930d2c merge base, with
upstream SHAs preserved by this --no-ff merge rather than a rebase or squash:

  96876db  fix(bin): require quota-axi 0.1.25 (kunchenguid#2300)
  85cefa9  fix(bin): prevent false Pi watcher alarms during hand-offs (kunchenguid#2304)
  81f7020  feat: support Cursor Agent CLI as a primary harness (kunchenguid#2305)
  5521323  feat(bin): add decline and repair paths for decision holds (kunchenguid#2330)
  db0280f  fix(bin): surface buried wake status lines once (kunchenguid#2331)
  88d0f2e  feat: add max Calm presentation level (kunchenguid#2334)

Two files conflicted.

bin/fm-spawn.sh takes upstream's version outright. The only fork-side change to
that file since the merge base was the Cursor attribution guard, which this fork
is deliberately dropping, so upstream's file is the whole intended result: the
Cursor --secondmate refusals are lifted and the per-task commit-msg hook install
is gone. The guard's remaining wiring in teardown, tests, and documentation is
removed in a follow-up commit on this branch.

docs/architecture.md preserves both sides. The fork's Option-A arm-layer
ownership stand-down contract stays verbatim, and upstream's Cursor clause is
folded into the primary-harness list in the same paragraph.

Every other dual-touched file was reviewed rather than trusted to auto-merge.
The Option-A supervision policy survives intact: fm_wake_append_resilient and
its callers and tests are unchanged, and bin/fm-watch.sh, bin/fm-watch-arm.sh,
and bin/fm-push-transition-lib.sh are byte-identical to the fork's prior main.
docs/watcher-continuity.md is the fork's file plus exactly upstream's three
Cursor and unread-status additions. bin/fm-session-lock-lib.sh keeps the fork's
cursor-agent identity match rather than a bare cursor match, and
bin/fm-harness.sh is untouched, so the cursor-like-filename reject fix stands.
@Quidge
Quidge force-pushed the fm/cursor-parity-sync branch from c24953f to 4440103 Compare August 14, 2026 00:13
@Quidge
Quidge merged commit ad45017 into main Aug 14, 2026
13 checks passed
@Quidge
Quidge deleted the fm/cursor-parity-sync branch August 14, 2026 00:51
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.

2 participants