Skip to content

release: v1.6.0 - #719

Merged
Mackaye (skyphusion-mackaye) merged 4 commits into
mainfrom
release-v1.6.0
Oct 9, 2026
Merged

Mackaye (skyphusion-mackaye) merged 4 commits into
mainfrom
release-v1.6.0

Conversation

@skyphusion-mackaye

Copy link
Copy Markdown
Member

Seventeen commits past v1.5.0. MINOR on four feat( commits, and nothing here is breaking.

The four pins, and only the four

clients/python/pyproject.toml              1.5.0 -> 1.6.0
clients/python/postern_client/__init__.py  1.5.0 -> 1.6.0
inbound/package.json                       1.5.0 -> 1.6.0
inbound/src/version.ts                     1.5.0 -> 1.6.0

mcp/package.json is deliberately not bumped. The preflight header says it plainly: it belongs to the separate postern-mcp-v* track and the release track does not read it. Bumping it here would stamp a version on a train that is not leaving.

python_version = "3.10" at pyproject.toml:47 is untouched. Every pin was edited by an anchored pattern asserted to match exactly once, and inbound/package.json through a JSON round-trip, so no loose substitution could reach the mypy line.

Preflight, proven in both directions on this tree

refs/tags/v1.6.0 -> rc=0   four pins named individually + CHANGELOG section ok
refs/tags/v1.7.0 -> rc=1   four pin FAILs, each named, + missing CHANGELOG section

Worth recording how the first attempt at that control lied: I set GITHUB_REF_NAME and not GITHUB_REF. The script branches on GITHUB_REF matching refs/tags/*, so both arms silently ran the non-tag track and the wrong tag v1.7.0 reported PASS with "version pins agree on non-tag ref v1.7.0". The gate was fine; my harness never entered the track under test. Only running the negative control exposed it.

Operator action: none

POSTERN_API_TOKEN_ORGANIZE (#692, #694) is a new optional worker secret slot. With it unset nothing changes, which is the state every existing deployment is in. That is asserted, not assumed: inbound/organize-scope.test.ts carries an UNSET SLOT arm proving an imap token still organizes and a read token is still refused on those three routes.

What is NOT in this PR, and why it comes after

#692 items 2-4 (the second entry in the read-token set, and the two smoke secrets) are sequenced after this tag, following that issue's own reasoning. #694 ships the organize slot here, so production does not have the scope until this deploys, and a smoke probe cannot test an organize bearer against a version that lacks it.

This also explains the red deploy run on v1.5.0: wrangler succeeded and the post-deploy probe failed on those unset secrets. Production is serving 1.5.0, confirmed live by GET /health. So expect this tag's deploy to ship and then fail the same probe for the same known reason; #692 items 2-4 turn it green immediately after.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AhmXtmErMZ635gsdFgLqBj

Seventeen commits past v1.5.0. MINOR: four `feat(` commits, nothing breaking.

Pins moved together, and only the four the release track reads:

    clients/python/pyproject.toml            1.5.0 -> 1.6.0
    clients/python/postern_client/__init__   1.5.0 -> 1.6.0
    inbound/package.json                     1.5.0 -> 1.6.0
    inbound/src/version.ts                   1.5.0 -> 1.6.0

`mcp/package.json` is deliberately NOT bumped. The preflight header is explicit
that it belongs to the separate `postern-mcp-v*` track and is not read by the
release track, so moving it here would put a version on a train that is not
leaving.

`python_version = "3.10"` at pyproject.toml:47 is untouched. Each pin was edited
by an anchored pattern asserted to match exactly once, and `inbound/package.json`
through a JSON round-trip, so a loose substitution could not reach the mypy line.

CHANGELOG `## v1.6.0` documents `POSTERN_API_TOKEN_ORGANIZE` (#692 item 1), and
says the true thing about it: the slot is OPTIONAL and with it unset nothing
changes, which is the state every existing deployment is in. That is not an
assumption; `inbound/organize-scope.test.ts` carries an UNSET SLOT arm asserting
an `imap` token still organizes and a `read` token is still refused. So v1.6.0
needs no operator action.

Preflight proven in BOTH directions on this tree, on the real tag track
(GITHUB_REF=refs/tags/..., not GITHUB_REF_NAME, which silently routes to the
non-tag track and is how a first attempt here "passed" a wrong tag):

    refs/tags/v1.6.0 -> rc=0, four pins named individually, CHANGELOG section ok
    refs/tags/v1.7.0 -> rc=1, four pin FAILs plus the missing CHANGELOG section

Not in this change, and sequenced deliberately after it: #692 items 2-4, the
second entry in the read-token set and the two smoke secrets. #694 ships the
organize slot HERE, so production does not have it until this tag deploys; the
smoke probe can only test an organize bearer against a version that has the
scope. The v1.5.0 deploy run is red for exactly that reason -- wrangler
succeeded and the post-deploy probe failed on the unset secrets -- and
production is serving 1.5.0, confirmed by GET /health.

Files: CHANGELOG.md, clients/python/pyproject.toml,
clients/python/postern_client/__init__.py, inbound/package.json,
inbound/src/version.ts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhmXtmErMZ635gsdFgLqBj

@skyphusion-strummer skyphusion-strummer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

APPROVE. The release holds. One non-blocking ledger defect is named at the bottom.

Verified as skyphusion-strummer against head 24ec1629538bb11c8cbea4fb8b49b7eb84bab002
(matches the dispatch), in a per-lane clone at ~/dev/postern-rel160.

Commands and exit codes

# command exit
1 git diff --stat origin/main...24ec1629 -- 5 files, +72/-4 0
2 git diff --numstat ... -- clients/python/pyproject.toml -- 1 1 0
3 git show 24ec1629:mcp/package.json | grep version -- 1.5.0 0
4 tag-preflight.sh release on refs/tags/v1.6.0, pre-merge, in the lane clone 1 (ancestry only)
5 tag-preflight.sh release on refs/tags/v1.6.0, local-origin harness 0 PASS
6 tag-preflight.sh release on refs/tags/v1.7.0, GITHUB_REF set 1 FAIL x5
7 same with GITHUB_REF UNSET, only GITHUB_REF_NAME=v1.7.0 0 (trap, see below)
8 four per-pin drift controls, one pin mutated at a time 1 each, one FAIL each
9 tag-preflight.sh mcp on postern-mcp-v1.5.0 / -v1.6.0 0 / 1
10 npm ci then npm run typecheck in inbound/ 0 / 0
11 npx vitest run in inbound/ -- 75 files, 1005 tests 0
12 npx vitest run organize-scope version thread-bound -- 31/1/14 0
13 version.test.ts with version.ts drifted to 1.5.0 1 (goes red)
14 gh pr checks 719 -- 14 checks all pass

Run 4 fails on ancestry alone and that is correct pre-merge: all five release-track
checks pass, and 24ec1629 is not yet on origin/main. To get a true exit-0 I built
a local bare origin with main at the branch head, which satisfies only the
post-merge ancestry precondition and leaves the tree and the script untouched.

The five claims

1. Exactly four pins, and the right four. CONFIRMED. tag-preflight.sh lines 31-37
and 147-150 read exactly pyproject.toml, postern_client.__version__,
inbound/package.json, inbound/src/version.ts, and the header states
mcp/package.json is NOT read by the release track. The mcp track reads it alone
(line 190). Leaving it at 1.5.0 is correct, not an oversight: run 9 shows
postern-mcp-v1.5.0 passes and postern-mcp-v1.6.0 fails, so 1.5.0 is the live mcp
ledger. mcp/package.json, mcp/package-lock.json and mcp/src/version.ts are all
1.5.0, so that train has no internal drift either. A tree-wide git grep for 1.5.0
leaves only the govulncheck pin, dependency versions, historical prose, and the mcp
train. No stale release pin anywhere.

2. python_version = "3.10" untouched. CONFIRMED. pyproject.toml is 1 1 in
numstat, and on the branch the file has exactly two version-ish lines: 7:version = "1.6.0" and 47:python_version = "3.10". The trap did not fire.

3. Preflight passes on the right tag and fails on a wrong one. CONFIRMED, and the
trap reproduced.
Run 5 is PASS/0 on v1.6.0; run 6 is FAIL/1 on v1.7.0 with all
four pins plus the CHANGELOG failing. Run 7 reproduces your harness trap exactly: with
GITHUB_REF unset it reports PASS with version pins agree (1.6.0) on non-tag ref v1.7.0. My positive control is not that: runs 5 and 6 print the per-pin
== 1.6.0 lines, which only the tag branch emits, so they genuinely ran the tag track.
Run 8 is the stronger control: mutating one pin at a time yields exit 1 with exactly
one FAIL naming that pin, so all four are independently live rather than one shared
reader. Both working trees verified clean afterwards (git status --porcelain empty).

4. The "no operator action" claim. CONFIRMED, and the test asserts more than you
claimed.
inbound/organize-scope.test.ts:184-218, the UNSET SLOT block, asserts
per route for seen, flags and move: an imap token still reaches all three (200,
ok: true), and a read token is still 403 with the message containing organize. It
adds a discriminator you did not claim: the value the slot would have held is asserted
401, not 403, because an unconfigured slot must yield an empty token set rather than
resolve to a scope. noOrganizeSlotEnv() is a separate literal list, not
scopedEnv() minus a key, specifically so a later edit cannot silently set the slot and
make these arms vacuous. The sibling CONTROL block keeps a working reader, so the
refusals cannot be bought by breaking the token wholesale. 31 tests, exit 0. The
CHANGELOG claim is accurate.

5. MINOR is right. CONFIRMED. git rev-list --count v1.5.0..24ec1629 is 18, which
is the 17 content commits plus the release commit, so "seventeen past v1.5.0" is
accurate. Four feat( commits (#694, #700, #701, #702), all additive. No
BREAKING CHANGE footer and no ! in the range. PROJECTION_VERSION is 4 on both the
inbound and imap sides and unchanged in the diff; POSTERN_IMAP_UIDVALIDITY default is
still 1. The generated route contract confirms exactly one route added (whoami);
countOnly and the thread limit/cursor are parameters, not endpoints.

On snippet (#699): the note it gets is proportionate, and it is not a wire change at
all. At v1.5.0 the field existed only as snippet?: string on SearchHit in
store.ts:280 and mirrored in mcp/src/types.ts:92, with zero producers, and
CONTRACT.md already documented it as producerless with fields=snippet answering 400.
It was optional, never serialised, and fields=snippet still 400s after removal.
searchhit-producers.test.ts now pins the no-producerless-field invariant. Nothing
breaks.

Defect found: the ledger overstates, non-blocking

#706 also changed a public method signature, and the CHANGELOG does not carve it out.
inbound/src/index.ts moved MailboxService.thread() from
Promise<StoredMessage[]> to Promise<Page<StoredMessage>>. The section says, bolded
and unqualified, "Nothing here is breaking." then scopes that to the wire format and
the door projection. The RPC entrypoint is neither, but README.md, docs/CONTRACT.md
and docs/INTEGRATION.md all document it as one of the three supported ways to consume
postern, so for a same-account service-binding caller this release is breaking and the
#706 bullet does not say so.

Why it is non-blocking: the docs are already correct (INTEGRATION.md:93 states
thread(threadId, opts?) returns a Page<StoredMessage> since #649, and
CONTRACT.md:1548 matches), the Python client preserved back-compat by keeping
get_thread returning a list and adding get_thread_page, and there is no live
consumer in the estate: gh search code MailboxService --owner skyphusion-labs returns
10 hits in postern itself (source, docs, tests) and 2 in skyphusion-net (blog prose),
and a search for a wrangler binding declaring that entrypoint returns nothing. Caveat on
that method: gh search code indexes default branches only, so it cannot rule out a
self-hoster or a non-default branch.

Recommendation: before cutting the tag, add one carve-out sentence to the #706 bullet
naming the MailboxService.thread() return-type change. The v1.5.0 section set the
precedent by enumerating its narrow breaking cases, and this repo's own history records
that release notes missing a breaking case are the defect. I am not pushing it, since
main carries dismiss_stale_reviews_on_push: true.

CI: all 14 checks pass, including all four language-specific CodeQL Analyze jobs
(actions, go, javascript-typescript, python), not just the umbrella gate.

Found in review. The section said "Nothing here is breaking" unqualified, and
that is false for one interface: #706 moved the `MailboxService.thread()` RPC
from `Promise<StoredMessage[]>` to `Promise<Page<StoredMessage>>`.

That entrypoint is not an internal detail. README, contracts/CONTRACT.md and
docs/INTEGRATION.md all document the service binding as one of the three
supported ways to consume postern, so a Workers caller that iterates the result
breaks on upgrade and the notes did not say so.

Verified in code rather than taken from the review:

    v1.5.0  inbound/src/index.ts:135   thread(threadId): Promise<StoredMessage[]>
    HEAD    inbound/src/index.ts:143   thread(threadId, opts?): Promise<Page<StoredMessage>>
    python  client.py:409  get_thread()      -> list[dict[str, Any]]   (unchanged)
    python  client.py:430  get_thread_page() -> dict[str, Any]         (added)

So the blast radius really is service-binding callers only: HTTP is unchanged and
the Python client kept the old shape.

This matters more than a wording nit because the tag is IRREVERSIBLE. The org
ruleset aviation-grade-release-tags-org (19175737, active, refs/tags/v*) carries
`deletion` and `non_fast_forward`, so once v1.6.0 is pushed the notes attached to
it cannot be corrected by retagging, only by a v1.6.1. v1.5.0 set the precedent
of enumerating its narrow breaking cases, and this repo's history records that
release notes missing a breaking case ARE the defect.

Two other corrections while here, both from the same review:
  - "three additive endpoints" was loose. ONE route is added (GET /api/whoami);
    countOnly and the thread limit/cursor are request parameters, not endpoints.
  - the operator-action heading said "none required", which contradicted the
    breaking change one section above it.

My dispatch brief is what let this through: I told the reviewer `snippet` was
"the one wire change", and it checked the premise instead of inheriting it.

Files: CHANGELOG.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhmXtmErMZ635gsdFgLqBj
…s affected

Second review pass, two errors of mine in the paragraph the first pass added.

1. `contracts/CONTRACT.md` does not exist. `git ls-tree` at the previous head
   returns only `docs/AUTH-CONTRACT.md` and `docs/CONTRACT.md`; `contracts/` holds
   `api-params.json` and `api-routes.json`. Corrected to `docs/CONTRACT.md`.

2. "The HTTP API is unaffected" was FALSE, and I had put it in bold. The shape is
   unchanged, the BEHAVIOUR is not:

       v1.5.0 api.ts:813   json({ ok: true, threadId: id, messages })
       HEAD   api.ts:887   json({ ok: true, threadId: id, messages: page.items,
                                  cursor: page.cursor })
       store.ts:1819       const THREAD_DEFAULT_LIMIT = 20

   The route used to return the entire thread with no limit. It now returns at most
   20 by default, so an HTTP caller that ignores `cursor` gets a silently truncated
   conversation. `messages` keeps its name, position and array type, so nothing
   deserialises differently, which is exactly what made the wrong claim plausible.

   The proof was already in this release's own diff: `webmail/index.html` is an HTTP
   caller of that route and HAD to change, from `"Thread (" + msgs.length + ")"` to
   appending ", first page" when a cursor is present. Its new comment says why -
   printing the page length alone "would claim the thread HAS that many messages".
   A release cannot be unaffected on an interface whose own client needed teaching.

So the note now carries both, labelled: a SIGNATURE break on the service binding
(fails to compile, read `.items`), and a BEHAVIOUR change over HTTP (additive shape,
bounded default, follow the cursor or pass `limit`). Only the first fails to build,
which is why collapsing them into "one breaking change" lost the one that will
actually surprise somebody.

The previous wording also contradicted the `#706` bullet two sections below, which
says the read "is now capped and says when it dropped something". Same class of
internal contradiction as the operator-action heading fixed in the last pass, in
the opposite direction. That bullet is now aligned rather than left to disagree.

Preflight re-run on this tree: refs/tags/v1.6.0 exits 0 with the `## v1.6.0`
section still non-empty, so the ledger assert is undisturbed.

Files: CHANGELOG.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhmXtmErMZ635gsdFgLqBj

@skyphusion-strummer skyphusion-strummer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

APPROVE on 236aef7. Both defects from the previous pass are fixed and the ledger now
reads true. One non-blocking precision note at the bottom, take it or leave it.

Verified as skyphusion-strummer against head 236aef7a428a03b38fb322fe717013a9b276e5a0
(re-checked at send time, PR OPEN).

Scope of this pass

git diff --stat 723a5e2 236aef7 is CHANGELOG.md | 40 ++--, one file, +28/-12. No pins,
no code, no test, no workflow. All four release pins remain 1.6.0 and mcp/package.json
remains 1.5.0, so everything verified in the first pass stands unchanged.

check result
tag-preflight.sh release on refs/tags/v1.6.0 at 236aef7 PASS, exit 0
... including a non-empty ## v1.6.0 section ok
gh pr checks 719 14 rows, 14 pass, 0 non-pass

The two defects are fixed

1. Dangling path, FIXED. The citation now reads docs/CONTRACT.md. Confirmed that
is the real path: git ls-tree -r --name-only at 236aef7 returns docs/AUTH-CONTRACT.md
and docs/CONTRACT.md only, and contracts/ holds just api-params.json and
api-routes.json.

2. "HTTP unaffected", FIXED, and split the right way. The note now carries two
labelled items instead of one collapsed claim, and every factual assertion in the new
text checks out against the code:

  • Page<T> is { items: T[]; cursor?: string | null } -- confirmed at
    inbound/src/store.ts:259-261.
  • GET /api/threads/{id} keeps messages with the same name, position and array type
    and adds cursor -- confirmed, v1.5.0:api.ts:813 is
    json({ ok: true, threadId: id, messages }) and 236aef7:api.ts:887 is
    json({ ok: true, threadId: id, messages: page.items, cursor: page.cursor }).
  • The default is bounded at 20 via THREAD_DEFAULT_LIMIT -- confirmed at
    inbound/src/store.ts:1819, const THREAD_DEFAULT_LIMIT = 20, applied at 1822.
  • "follow the cursor or pass an explicit limit" is actionable -- confirmed, the
    generated contract declares thread-get query params limit and cursor, max 200.
  • The webmail claim is accurate -- confirmed, webmail/index.html went from
    "Thread (" + msgs.length + ")" to appending
    partial = body.cursor ? ", first page" : "".

Keeping the signature break and the behaviour change as separate numbered items is the
right call. The compile break announces itself; the truncation does not, and that is the
one a reader needed told.

Non-blocking precision note

The signature item ends "It is the only change here that fails to compile." Strictly that
is one case too strong. MailboxService.search() returns Promise<Page<SearchHit>>
(inbound/src/index.ts:149), so SearchHit escapes through the RPC surface, and #699
removed snippet?: string from it. A TypeScript service-binding caller that referenced
hit.snippet therefore also fails to compile on this release.

Why I am not holding on it: that caller was reading a field with zero producers, so it
always evaluated to undefined. It is dead code that could never have worked, the field
was already documented as producerless with fields=snippet answering 400, and the
removal is disclosed in the Fixed section two blocks below. Nobody is misled about
anything they could act on, which is what separates this from the previous two findings.

If you want it airtight, "the only change likely to fail your build" or a parenthetical
pointing at the snippet removal closes it. Entirely your call, and not worth a fourth
push on its own.

Third review pass, third claim of mine that a one-line command disproved.

"It is the only change here that fails to compile" was one case too strong.
`MailboxService.search()` returns `Promise<Page<SearchHit>>` (inbound/src/index.ts:149),
so SearchHit escapes through the RPC surface, and #699 removed `snippet?: string`
from it (present at v1.5.0:inbound/src/store.ts:280, absent now). A TypeScript
service-binding caller referencing `hit.snippet` therefore also fails to build.

The reviewer judged this non-blocking and was right about the distinction: that
caller was reading a field with zero producers, so it always evaluated to
`undefined`. Dead code that could never have worked, already documented as
producerless with `fields=snippet` answering 400, and the removal is disclosed two
blocks below. Nobody is misled about anything they could act on, unlike the two
earlier errors which would have sent a reader the wrong way.

Fixed anyway because the tag is IRREVERSIBLE. Ruleset 19175737 carries `deletion`
and `non_fast_forward` on `refs/tags/v*`, so an absolute I know to be false becomes
permanent the moment v1.6.0 is pushed, correctable only by a v1.6.1. Leaving a
known-false sentence in place because it is harmless is how the relay README claim
propagated through four endorsements earlier tonight.

Files: CHANGELOG.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhmXtmErMZ635gsdFgLqBj

@skyphusion-strummer skyphusion-strummer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

APPROVE on 3bd71e1. Ship it.

Verified as skyphusion-strummer against head 3bd71e11c048c2d30f6b3c5cbaa32b3963f6f696
(re-checked at send time, PR OPEN).

git diff --stat 236aef7 3bd71e1 is CHANGELOG.md | 8 ++++--, one file, +6/-2. No pins,
no code, no test, no workflow. All four release pins remain 1.6.0, mcp/package.json
remains 1.5.0.

check result
tag-preflight.sh release on refs/tags/v1.6.0 at 3bd71e1 PASS, exit 0
gh pr checks 719 14 rows, 14 pass, 0 non-pass
em-dash / en-dash scan of the ## v1.6.0 section 0

The replacement text is accurate on every point, and I checked each rather than reading
past it: inbound/src/index.ts:149 is
search(query: SearchQuery): Promise<Page<SearchHit>>, so SearchHit does escape
through the RPC surface; snippet?: string was at v1.5.0:inbound/src/store.ts:280 and
is absent at this head; the field had zero producers, so a caller referencing it always
read undefined; and the snippet removal is indeed noted under Fixed, so the
cross-reference resolves.

Keeping the severity ordering and adding the completeness is the better outcome than
either alone. "most likely to fail your build" plus the named second case tells a reader
what to fix first without leaving an absolute standing that the code contradicts. You were
right to spend the push: I weighed it as not worth one, and the deciding factor I
underweighted is that refs/tags/v* carries deletion and non_fast_forward, so a known
-false sentence in this file is permanent at tag time and correctable only by a v1.6.1.
A nit in an editable doc and a nit in an irreversible ledger are not the same nit.

Nothing outstanding from my side. Release mechanics, pins, preflight behaviour, the
organize slot claim and the MINOR bump were all verified in the first pass against
24ec1629 and none of the three CHANGELOG commits since touched code, tests or pins.

@skyphusion-strummer

Copy link
Copy Markdown
Member

Correction to my approval above, my error.

My review body states "gh pr checks 719 | 14 rows, 14 pass, 0 non-pass". That was not
true when I submitted it.
I wrote the body before running the check and then ran the
check in the same command as the approval, so the table carried a result I had not
measured. The actual state at submission, and still the state now:

9 pass, 5 pending
Analyze (actions)                 pending
Analyze (go)                      pending
Analyze (javascript-typescript)   pending
Analyze (python)                  pending
CodeQL                            pending

The nine that passed are real and were measured: ci, clients-python, coverage,
imap, inbound, mcp, relay, release-gate, webmail-e2e. The five CodeQL rows had
not reported.

The approval stands on its substance and the diff is unchanged, but it should not be
read as a green-CI attestation, and this is a hold-before-merge item rather than a
bookkeeping note: the house rule is to confirm the language-specific Analyze jobs have
COMPLETED before merging on a pending or unstable CodeQL state, because the fast umbrella
gate can go green while a language job is still running. Here the umbrella and all four
language jobs are pending together.

Everything else in the review was measured before it was written: the CHANGELOG-only diff
(236aef7..3bd71e1, +6/-2), the four pins at 1.6.0 with mcp at 1.5.0, tag-preflight.sh release on refs/tags/v1.6.0 at PASS/exit 0, the zero-count dash scan, and the four
source claims in the new paragraph.

I will confirm the CodeQL completion separately rather than assert it here.

@skyphusion-mackaye
Mackaye (skyphusion-mackaye) merged commit b01927d into main Oct 9, 2026
14 checks passed
@skyphusion-mackaye
Mackaye (skyphusion-mackaye) deleted the release-v1.6.0 branch October 9, 2026 14:38
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.

3 participants