Skip to content

fix(cloud-connection): an install-local uninstall withdraws the package's flows from the automation engine and unbinds their triggers (#27395) - #27530

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-30b1mx
Oct 29, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-30b1mx

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread
Fixes #27395
Clause-②: no
Metadata-protocol: none
Skills-docs: none — nothing a metadata author writes changes, and no skill or doc teaches the uninstall leaving flows live; the fix makes the door's existing note true
Ruling-ref: triage 6489212277

维护者速读

  • 改了什么:本地安装的卸载接口(DELETE /api/v1/marketplace/install-local/ID)在撤回注册表、跑完卸载清理之后,最后再宣告一次 metadata:reloaded(和安装时热加载宣告的是同一个信号、同一个载荷)。自动化引擎收到后重新同步,把这个包的流程撤掉,并在同一步解绑它们的记录触发和定时触发。宣告失败时,卸载照样成功,cleanups 里多一条名为 metadata:reloaded 的失败结果,说明里写明流程可能留到下次重启。
  • 为什么改:以前卸载后,元数据里流程已经 404,引擎里却还是 active:按名触发照样跑、写运行记录,记录触发和定时触发也还挂着,直到别的什么事碰巧触发一次重载(QA QA run · release-18.3.0-w3-manual-api (25/25) · c4c515ad · 2026-10-29 · 23 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27392 复现两次)。卸载接口自己的说明还写着「已从运行中的内核撤回」。按 triage 裁决,卸载走重载用的同一条撤回路径,不另起一份引擎侧清单。
  • 风险与回滚:只改卸载接口这一处,安装路径不动。多出的一次重新同步和安装时那次完全一样(流程重同步、作者钩子与动作重同步、幂等的建表同步)。注册表拒绝撤回时不宣告,因为包还在。回滚 = revert 本 PR。
  • 先看:packages/cloud-connection/src/marketplace-install-local-plugin.ts 里 handleUninstall 末尾新加的宣告和说明文字的拼装,以及新方法 announceUninstall;然后是 dogfood 新测试 packages/qa/dogfood/test/install-local-uninstall-flows-withdrawn.dogfood.test.ts。
  • 两分钟验证:pnpm --filter @objectstack/cloud-connection exec vitest run --maxWorkers=2 src/marketplace-install-local-uninstall-resync.test.ts,应见 7 个用例全部通过(宣告一次、在撤回和清理之后、失败作为一条结果上报,以及没卸载成功时不宣告)。
  • 需要你做的:无,席位落地。

Under the claim 6493772753. DELETE /api/v1/marketplace/install-local/:manifestId now announces metadata:reloaded after it withdraws the package from the registry and runs the cleanups, so the automation engine withdraws the package's flows and unbinds their triggers in the same request. Before, nothing told the engine: the flows stayed active and triggerable until some unrelated reload.

Branch claude/project-thread-30b1mx (the card thread's harness-pinned branch; it names no issue, so the claim is the identity record), cut from origin/main at eef83734d9, with origin/main ded67bfb59 merged in before this PR was opened.

What changes

The mechanism, measured

  • The uninstall door withdrew the package with SchemaRegistry.uninstallPackage, withdrew the object copies from the metadata service, ran the protocol's uninstall cleanups, and returned. It announced nothing.
  • service-automation withdraws a flow in exactly one place after boot: resyncFlowsFromProtocol, on metadata:reloaded. It re-reads the protocol's flow view and calls withdrawFlow for every flow it had armed that the view no longer lists. withdrawFlow calls deactivateFlowTrigger first, so the trigger is unbound in the same step.
  • The install door announces that signal (announceHotInstall, { changed: ['app/ID'] }). That is why a view publish, or any other package's install, cleared the stale flows in the QA run.

So the dispatch hypothesis held as written. The ruling (triage 6489212277, verbatim): "The uninstall door drives the same unregister path a reload uses. It is one teardown, not a second engine-side list."

The change (packages/cloud-connection/src/marketplace-install-local-plugin.ts)

  • handleUninstall: after the cleanups, announceUninstall(ctx, manifestId) runs last. It is never run before the withdrawal and the cleanups, for the window the door's existing comment describes. It is skipped when the registry refused the withdrawal: the package is still registered, so a re-sync would only read it back.
  • announceUninstall announces metadata:reloaded with the install's payload, { changed: ['app/MANIFEST_ID'] }. It never throws. If a subscriber throws, or the context cannot announce, it returns one failed outcome named metadata:reloaded (the new KERNEL_RESYNC constant, named for the event, as registry.uninstallPackage and metadata.unregister are named for their verbs). That outcome rides on cleanups the way a refused registry withdrawal does. The cause and the remedy (restart) go to the operator log at warn, the level the install's announce failure uses, and never onto the wire.
  • The note and the info log are composed per outcome. When the re-sync did not run, the note says the engine can still hold the package's flows until the next restart, naming the metadata:reloaded entry. The copy-withdrawal sentence is unchanged, byte for byte. When everything ran, the note's claim ("withdrawn from the running kernel") is now true.
  • ⛔ Nothing in the door withdraws a flow or unbinds a trigger itself. No engine-side list of the package's flows is kept.
  • The module note's DELETE paragraph says so.

packages/services/service-automation/src/plugin.ts was not needed and is not touched. No packages/spec change.

Changeset

.changeset/27395-install-local-uninstall-flow-resync.md: @objectstack/cloud-connection patch, with Clause-②: no and Metadata-protocol: none copied from the claim.

Tests

  • New, end to end: packages/qa/dogfood/test/install-local-uninstall-flows-withdrawn.dogfood.test.ts. One showcase boot with MarketplaceInstallLocalPlugin mounted. It installs an inline package that ships two flows: one run by name, and one bound to record-after-insert on showcase_category, an object that outlives the uninstall. Five cases:
    1. PRECONDITION: the install hot-loads both flows as the package's (_packageId), and each runs once: the first through the trigger door, the second through an insert. Each leaves one run in the engine's listing and one sys_automation_run row.
    2. The uninstall answers 200 with no failed outcome, and GET /meta/flow/NAME answers 404 (the half that already worked).
    3. GET /automation/NAME answers 404 for both flows.
    4. POST /automation/NAME/trigger answers 404, and no run is listed or written.
    5. An insert into the watched object runs nothing: the record trigger was unbound in the same step.
  • New, the door's half: packages/cloud-connection/src/marketplace-install-local-uninstall-resync.test.ts, 7 cases. One ordered event log over the registry, the cleanup runner and the kernel's trigger pins: exactly one metadata:reloaded, naming app/ID, after the withdrawal and after the cleanups, with the ledger entry gone. Nothing is announced for a refused caller, an unknown id, a failed ledger write, or a refused registry withdrawal. A throwing subscriber and a context with no trigger each give one failed metadata:reloaded outcome, last; the cause stays in the log.
  • Moved pins (rig only): the three existing uninstall rigs (…-uninstall-withdrawal, …-uninstall-cleanups, …-uninstall-meta-reads) gain trigger: async () => undefined on their kernel context. Every real PluginContext declares trigger. Without it, these rigs now get the failed re-sync outcome on cleanups, which their toEqual assertions on cleanups and their empty-warning assertions refuse. No assertion changed.

Verification

All local readings below are on 7cb1ca3adb (the merge of ded67bfb59) unless a line says otherwise.

Red first, on the base source (eef8373)

The red tests were committed first (243399d5). Each leg wrote the base blob of the plugin file over the fix with git show, ran the pins, and restored from HEAD. Every restore was proved by git hash-object equal to the HEAD blob and a clean git status --porcelain.

  • Unit: src/marketplace-install-local-uninstall-resync.test.ts → 3 failed / 4 passed. The three positive cases fail. The four "announces nothing" controls pass on the base, as they should.
  • Dogfood, after rebuilding @objectstack/cloud-connection from the base blob (ablation-dist-preflight … 'announceUninstall' --absent → the marker is absent from all 6 built files) → 3 failed / 2 passed. The precondition and the 200 passed; the three engine cases failed with the QA run's exact readings:
    • GET /automation/qauninst_manual_probe → 200 status: active, _provenance: package, _packageId: com.example.qauninst;
    • the trigger → 200, the run completed;
    • the record flow: listed 2 / rows 2, expected 1 / 1.
Green, and the ablation (ablation-replace, fix committed first)
  • Green, after the fix was rebuilt (preflight: announceUninstall present in 4 built files, tree clean): dogfood 5/5; unit 7/7.
  • Mutate leg (scripts/ablation-replace.mjs). The anchor const resync = withdrawal ? undefined : await this.announceUninstall(ctx, manifestId); hit once and was replaced by void this.announceUninstall; const resync: UninstallCleanupOutcome | undefined = ((globalThis as any).ablated27395 = undefined);. Blob e25af962d8ba → 3bdeeea26dea. Build exit 0, and preflight found the marker in 2 built files. Result: dogfood 3 failed / 2 passed (the same three cases), unit 3 failed / 4 passed. The restore checked blob == HEAD and an empty git diff HEAD.
    • A first mutate leg without the void read is not counted: its JS bundles carried the marker, but the DTS build exited 1 on TS6133 (the now-unused private). It gave the same 3 red / 3 red.
  • Restore leg: rebuild exit 0; preflight ablated27395 --absent found the marker absent from all 6 built files, tree clean; dogfood 5/5.
Package suite, typecheck and gates

On 7cb1ca3adb, after pnpm install --frozen-lockfile and a rebuild of the dogfood closure plus @objectstack/driver-turso (lock VERDICT command-exit 0, 67/67 tasks):

  • pnpm --filter @objectstack/cloud-connection test → VERDICT command-exit 0, Test Files 60 passed (60), Tests 754 passed (754).
  • pnpm --filter @objectstack/cloud-connection typecheck → VERDICT command-exit 0.
  • pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/install-local-uninstall-flows-withdrawn.dogfood.test.ts → VERDICT command-exit 0, 5 passed (5).
  • Gates: node scripts/pm/dispatch-gates.mjs --commands derived 64 commands on this tree. All 64 ran, each exit captured before any pipe; 64 exit 0. pnpm check:dual-build-cjs-loads first answered exit 3 (seven packages outside the closure had no dist/); those seven were built and it then exited 0, so that is the recorded reading. dispatch-gates --ran → "64 derived, 64 run, 0 NOT-MEASURED, 0 UNRUN", a derived zero (every line carries its exit code, none is 3).
  • test:repo was not run locally: the diff edits no repo-project test and the derivation does not name it. CI's Test Core runs it.

Acceptance notes

  • Serial order. No code was edited before the claim 6493772753 named this branch.
  • Overlap with feat(service-automation, runtime, spec): connector credential store and open-tier credentialRef chain (#27237) #27344 (os-bill, open, also edits this plugin file). Its hunks are at base lines 214, 734, 1954, 1969 and 3464. This diff's hunks are at 111, 303 and 2291 to 2308, so they are disjoint. A bare-clone git merge-tree --write-tree of this head against feat(service-automation, runtime, spec): connector credential store and open-tier credentialRef chain (#27237) #27344's head 355edc0624 exits 0 (tree 674cf2d5f8). Whichever lands second merges main.
  • The install door's own re-sync failure is still only logged (announceHotInstall, unchanged): the install answers 200 and says nothing on the wire. That is outside this card; this PR reports the uninstall's failure on the response because the uninstall already reports partial completion there (cleanups).
  • A sibling door, not measured. The runtime's DELETE /api/v1/packages/:id (packages/runtime/src/domains/packages.ts) also withdraws through deletePackage / uninstallPackage and announces no metadata:reloaded. Whether its flows stay live depends on what deletePackage's stored-row deletes signal to the engine, and that was not measured here. It is a read-only inference, so per the dev contract it is noted, not filed.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (Not touched.)
  • 2. Every name I added uses the casing for its kind (KERNEL_RESYNC, announceUninstall).
  • 3. No formatter ran; lint is CI's run.
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A patch changeset for @objectstack/cloud-connection; both declaration lines are filled in here and in the changeset.
  • 6. packages/spec not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English, apart from the maintainer quick-read block the project asks for.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L6bhgTsswEK7wz8UFCtF5z


Generated by Claude Code

…'s flows live in the engine (red)

Pins the door's half (one metadata:reloaded, last, after the withdrawal
and the cleanups; a failed re-sync is a failed outcome on the response)
and the composed half on the real showcase boot (GET /automation/NAME
404, the trigger door 404 with no run row, the record trigger unbound).
Both fail on the base: the door announces nothing.

Claude-Session: https://claude.ai/code/session_01L6bhgTsswEK7wz8UFCtF5z
Co-authored-by: Claude <noreply@anthropic.com>
…reloaded, so the engine withdraws the package's flows and unbinds their triggers

The DELETE door withdrew the package from the registry and ran the
cleanups but told the running kernel nothing; the automation engine
withdraws a flow only in its re-sync on metadata:reloaded, so the
uninstalled package's flows stayed active and triggerable until an
unrelated reload. The door now announces the same re-sync the install's
hot load does, last, after the withdrawal and the cleanups; a re-sync
that does not run is one failed outcome on the response. The existing
uninstall rigs gain the trigger every kernel context has.

Claude-Session: https://claude.ai/code/session_01L6bhgTsswEK7wz8UFCtF5z
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Oct 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cloud-connection, touching 4 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/cli.mdx (via MarketplaceInstallLocalPlugin (symbol, a top-level class))
What this run could not see
  • the SDK route bridge reached 58 of 210 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 5 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 57c51aab4d2f63293676e9412daed8a5fc54c1bc → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 5ed5a730f021089920df2ebfcb45b9f3219e0016 — the merge of head 7cb1ca3adb07d6f0fc545dd3cc3d6109797410f3 into base 57c51aab4d2f63293676e9412daed8a5fc54c1bc, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 5ed5a730f021089920df2ebfcb45b9f3219e0016 && git checkout 5ed5a730f021089920df2ebfcb45b9f3219e0016
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 57c51aab4d2f63293676e9412daed8a5fc54c1bc 7cb1ca3adb07d6f0fc545dd3cc3d6109797410f3 && git checkout -B drift-repro 57c51aab4d2f63293676e9412daed8a5fc54c1bc && git merge --no-ff 7cb1ca3adb07d6f0fc545dd3cc3d6109797410f3

node scripts/docs-audit/affected-docs.mjs --json 57c51aab4d2f63293676e9412daed8a5fc54c1bc

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 57c51aab4d2f63293676e9412daed8a5fc54c1bc → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

维护者速读(席位终稿)

  • 改了什么:本地安装的卸载接口(DELETE /api/v1/marketplace/install-local/ID)撤回注册表、跑完卸载清理之后,最后宣告一次 metadata:reloaded。这和安装时热加载宣告的是同一个信号、同一个载荷。自动化引擎收到后重新同步:撤掉这个包的流程,并在同一步解绑它们的记录触发和定时触发。宣告失败时卸载照样成功,cleanups 里多一条名为 metadata:reloaded 的失败结果,说明里写明流程可能留到下次重启。
  • 为什么改:以前卸载后,元数据里的流程已经 404,引擎里却还是 active。按名触发照样能跑、照样写运行记录,记录触发和定时触发也都还挂着,要等别的事碰巧触发一次重载才消失(QA QA run · release-18.3.0-w3-manual-api (25/25) · c4c515ad · 2026-10-29 · 23 PASS / 2 PARTIAL / 0 FAIL / 0 BLOCKED / 0 NOT-RUN #27392 复现过两次)。卸载接口自己的说明还写着「已从运行中的内核撤回」。按分诊裁决,卸载走重载用的同一条撤回路径,不另起一份引擎侧清单。
  • 风险与回滚:只改卸载接口这一处,安装路径不动。多出的这次重新同步和安装时那次完全一样。注册表拒绝撤回时不宣告,因为包还在。回滚即 revert 本 PR。
  • 先看:marketplace-install-local-plugin.ts 里 handleUninstall 末尾新加的宣告和说明文字的拼装,以及新方法 announceUninstall;dogfood 新测试 install-local-uninstall-flows-withdrawn.dogfood.test.ts。
  • 两分钟验证:pnpm --filter @objectstack/cloud-connection exec vitest run --maxWorkers=2 src/marketplace-install-local-uninstall-resync.test.ts,应见 7 个用例全部通过。
  • 需要你做的:无,席位落地(非受管面、非收窄、不欠契约复审)。
  • 席位意见:收下。修复只是让卸载补发安装本来就发的那个信号,没有第二份撤回逻辑;dogfood 端到端证明按名触发、记录触发都随卸载失效。

席位核对 — ACCEPT · domain:server#1 · head 7cb1ca3a · 2026-10-29T11:18Z

  • Shape: 7 files, +623/−6 (629 lines). The source change is in marketplace-install-local-plugin.ts (+99/−6): KERNEL_RESYNC, the announce in handleUninstall, announceUninstall, and the note and log wording. There is one new unit file (+268) and one new dogfood file (+233). Three existing uninstall rigs gain a no-op trigger (rig only; no assertion changed). There is one patch changeset. check-governed-merges --pr 27530: 0 of 7 paths governed, under the 3,000-line bar. No packages/spec, and no service-automation change.
  • Premise, measured by the seat: I read the diff.
    • The announce sits after the registry withdrawal and the cleanups, as the existing comment on the uninstall window requires.
    • It is skipped when the registry refused the withdrawal, because the package is still registered.
    • Its payload { changed: ['app/ID'] } is the install door's.
    • It never throws, and a failure lands as one failed cleanups outcome, with the cause in the warn log only.
    • Nothing withdraws a flow or unbinds a trigger itself, so the triage ruling holds: one teardown, the reload's.
  • Tests:
    • The unit file has 7 cases: announced exactly once and last, nothing announced on a refused caller, an unknown id, a failed ledger write or a refused withdrawal, and the two failure arms.
    • The dogfood file asserts end to end that GET /automation/NAME answers 404, the trigger door answers 404 with no run row, and an insert into the watched object runs nothing.
    • Red before the fix: unit 3 red / 4 green, dogfood 3 red / 2 green.
    • The ablation-replace legs re-red, and the restore is back to 5/5.
  • Gates:
    • On 7cb1ca3a: 35 success and 14 skipped, none other. check-expected-skips --pr 27530 (roster pinned to main): OK. mergeable_state: clean.
    • The dev's derived gates: 64 of 64, --ran with 0 NOT-MEASURED.
  • Declaration:
    • Clause-②: no is right: the door's own note already claimed the withdrawal, so the change pulls behaviour back to the declared contract, with no new accept set and no new export.
    • Metadata-protocol: none and patch fit a bug fix in one plugin.
    • I read the changeset sentence by sentence against the diff (Before, Now, the failure arm, Unchanged), and it matches.
  • Accepted deviations: the three rigs' no-op trigger member is declared in the PR body. The draft opened with no assignee and no review request, per pm-dispatch(review): a PR reaches a human only after the seat's ACCEPT and a same-head contract PASS: no seat assignee at the draft open, the approver request is the seat's hand-off, a PR landed owing a review is re-reviewed with findings filed as cards #27385. The seat's earlier assignment was withdrawn.
  • Out of scope + Skills-docs: Skills-docs: none holds, since nothing a metadata author writes changes. Open PR feat(service-automation, runtime, spec): connector credential store and open-tier credentialRef chain (#27237) #27344 (os-bill) edits the same file: git merge-tree exits 0 and the hunks are disjoint. Whichever lands later merges main.
  • Landing: the PR is not governed and owes no contract review, so it goes ready, then auto-merge through the queue. install-local: uninstalling a package (DELETE /api/v1/marketplace/install-local/ID) leaves its flows registered and triggerable in the automation engine until an unrelated metadata reload #27395 closes on merge (Fixes #27395). It is retested on the next QA wave (anchor [sweep] v18.3.0 release test sweep #27377 §5).

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 29, 2026 11:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit aef631b Oct 29, 2026
50 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-30b1mx branch October 29, 2026 11:36
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

Landed · domain:server#1 · 2026-10-29T11:39Z

Reading Value
PR #27530 merged at 2026-10-29T11:36Z, merge commit aef631b80b, head 7cb1ca3a (the ACCEPTed head)
Card #27395 closed / completed by this PR's Fixes

State change: pm:dispatched removed from #27395. No other card was closed by this PR's body. The next QA wave retests it (anchor #27377 §5).


Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

2 participants