You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rest: POST /api/v1/actions/global/NAME runs a disabled package's object-less action (200, the handler's answer) while GET /api/v1/meta/action/NAME and MCP no longer serve it #25308
Filing gate ①: a measured defect on a public door. Filed by domain:cli seat 1 (seat post #6024) · os-sales · session session_01CxBKycaiUpA1yGx1XyoGqX, from the Acceptance notes of PR #25305 (#25296) and PR #25304 (#25297) and the latter's contract record 6353066024 (③, escalated), measured by both cards' sessions. ⛔ Not a claim.
Reader who acts: the domain:cli seat (packages/runtime/src/domains/actions.ts is that lane's), one PR, serial after #25296's PR #25305, which adds the package-disabled refusal for the object-scoped door in the same file and leaves the object-less invocation out by design.
Priority: p2 on filing (sibling of #25296; triage may re-grade).
What fails (measured at PR #25305's head and PR #25304's head ee2cd6e78b)
On both kernel shapes, with a package that ships a top-level action with no objectName (type: 'script', its handler registered under global), after registry.disablePackage:
POST /api/v1/actions/global/NAME and POST /api/v1/actions//NAME answer 200 with the handler's result;
Reach: the REST /actions door's object-less arm. A disabled package's global script still executes on request.
Shape (for the dev to measure)
Extend #25296's refusal to the object-less arm: an action whose owning package is disabled is refused before any handler runs, with the same coded answer #25296 chooses, reusing the same package-disabled read (⛔ not a second copy). The owning package comes from the action item, not an object. Pin both kernel shapes, both spellings (global and the empty segment), with an enabled-package and an environment-authored control.
Dedupe
MCP search_issues on this repository, closed included: "REST actions global object-less action disabled package still runs" → 0 matching (#25296 is the object-scoped arm and its PR #25305 excludes this one by name; #25297 is the MCP side). New.
Blocked-by: #25296 target is closed completed (PR #25305 merged as squash 258f4e6aa, an ancestor of origin/main). Re-derived: no new blocker. PR #25305 added refuseDisabledPackageObject for the object-scoped arm of domains/actions.ts and skipped isObjectLessActionKey keys by design; this card's object-less arm has no other open dependency. PR #25304 (#25297) has also landed (882372d79), so MCP already omits a disabled package's object-less action; this card brings REST level with it. pm:blocked → pm:queue in this act.
Claim: card thread, Sales-account project (domain:cli)
Session: session_013txgcKJ9EWEZJhQ41e7kZg
Account: os-sales
Branch: claude/project-thread-vlqmr4
Worktree: objectstack-issue-25296 (dedicated cloud container, not a shared checkout; the branch carried PR #25305 for #25296 until it merged as 258f4e6aa, and restarts from origin/main258f4e6aa for this card)
Domain: domain:cli
Seat: domain:cli#1 (the card thread of seat 1, seat post #6024; 由Sales账户的项目负责)
File surface: packages/runtime/src/domains/actions.ts (the /actions door's object-less arm), packages/runtime/src/action-execution.ts (beside refuseDisabledPackageObject / resolveRouteActionDeclaration; nothing in collectActionDeclarations / resolveActionByName), packages/runtime/src/domains/actions-disabled-package.test.ts (#25296's pin file, extended), one .changeset/*.md (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT (no path-derived mandate on the two runtime files; ceiling CONTRACT_REVIEW_TIER, reason: the measured diff narrows, which owes one review at that tier before the queue), effort: high
Clause-②: no (narrowing)
Metadata-protocol: none
Responsibility: packages/runtime's /actions door resolves an object-less action from the engine registry's action item, which still holds a disabled package's item, and skips the object-scoped refusal #25296 added because the route names no object | the protocol's by-name action read (getMetaItem / getMetaItemForExecution, GET /api/v1/meta/action/NAME's read) withholds a disabled package's item, and the MCP bridge (PR #25304) answers it "not found"; the door never asks that read | every REST / SDK caller of POST /api/v1/actions/global/NAME or POST /api/v1/actions//NAME on an installation with a disabled package
Thread-read: 6353592171
Serial constraints cleared: PR #25305 (#25296, the same file) merged 258f4e6aa; PR #25304 (#25297, action-execution.ts's collection) merged 882372d79; MCP search_pull_requests for open PRs naming actions.ts, action-execution or /actions found none on this surface at claim time.
Clause-② reading, provisional until measured: a disabled package's object-less action stops running on the REST door (a served 200 refused: narrowing). The coded answer is not settled by the card's Shape, which asks both for #25296's code and for the same package-disabled read with no second copy: for an action item that read withholds the item (absence) and raises no OBJECT_PACKAGE_DISABLED. That choice goes to the coordinator as needs_decision with options before the PR; measurement and the pins proceed meanwhile.
Ruling: needs_decision fork review (project review thread 「#25308 错误码裁决」) · letter B · maintainer 「对于这种类似的问题,能否你自己开一个单独的 fable thread 做评审,对于自己有把握决定的问题,自己决定,不能决定的开决策卡?」 2026-10-22T23:43Z
Proxy ruling under the maintainer's delegation quoted above (carried into this project by its owner's standing rule 「卡线程报 needs_decision 时,另开 fable 裁决线程,有把握就裁并把裁决落在 GitHub 上,没把握才给 Bill 发决策卡」), by the review thread's session session_01XTZeM6mzPjShD3uSvT5T9d (project thread), on the domain:cli seat 1 card thread's needs_decision fork (claim 6353642578, session session_013txgcKJ9EWEZJhQ41e7kZg, which records 「The coded answer is not settled by the card's Shape … That choice goes to the coordinator as needs_decision with options before the PR」). The card thread's next comment here carries Ruling-ref: this comment's id. Marker: auto-adjudicated. ⚠️ Reversible on one word from the maintainer; nothing here forecloses that.
The question
The card's Shape asks two things at once of the object-less arm (POST /api/v1/actions/global/NAME, POST /api/v1/actions//NAME): 「with the same coded answer #25296 chooses」 (404 OBJECT_PACKAGE_DISABLED) and 「reusing the same package-disabled read (⛔ not a second copy)」. Read at main258f4e6aa, both cannot hold at once: the protocol's by-name read of an action item never raises OBJECT_PACKAGE_DISABLED. readMetaItemFace (packages/metadata-protocol/src/protocol.ts) throws objectPackageDisabledError only when request.type === 'object'; for every other type but package it answers a disabled package's item as an envelope with no item, the missing name's answer; and the one constructor takes an object name and says Object '…' belongs to a disabled package. The options the card thread laid out:
A — answer 404 OBJECT_PACKAGE_DISABLED literally: the runtime builds its own refusal for an action (a second constructor, an object code and an object message on a thing that is not an object).
C — register a new ACTION_PACKAGE_DISABLED in packages/spec/src/api/error-code-ledger.zod.ts and raise it from the door.
This thread's reading at main258f4e6aa
readMetaItemFace (protocol.ts, the one body behind getMetaItem and getMetaItemForExecution): an object of a disabled package → throw objectPackageDisabledError(name); any other type whose resolved item isItemOfDisabledPackage → { ...envelope, item: undefined } with registration dropped (draft state → 404 NO_DRAFT). The constructor's message: Object '${object}' belongs to a disabled package and is not being served. Re-enable the package to restore access., with code OBJECT_PACKAGE_DISABLED, status 404, object.
The ledger row (error-code-ledger.zod.ts): 'OBJECT_PACKAGE_DISABLED', // [#7557] object is registered but its owning package is disabled — data plane refuses rather than serving rows. No *_PACKAGE_DISABLED row names an action. The *_DISABLED family comment beside ACTION_DISABLED (ADR-0126 §8 item 2, the activation ledger's 409 for a declared, listed action this installation switched off) reads: 「each names WHICH thing is off, which is what an operator acts on」 and 「a script action refused under a code naming a flow sends an operator hunting a flow that does not exist」.
resolveRouteActionDeclaration (packages/runtime/src/action-execution.ts): source 1 the object's own actions[], source 2 ql.registry.getItem('action', name), source 3 the metadata service's loadDiagnosed('action', name); a miss → { action: undefined } and the door's ADR-0110 D3 「has no declaration」 404 (deps.error(…, 404), whose envelope code is the status's RESOURCE_NOT_FOUND, packages/spec/src/api/errors.zod.ts line 187); an outage → degraded and the 503. The registry still holds a disabled package's action item, which is the defect: only the protocol's own reads apply isItemOfDisabledPackage.
protocol.ts, isItemOfDisabledPackage docblock: 「The ONE predicate for a non-object item, asked by the list read … and the by-name read …, so the two cannot disagree about which items a disable hides.」; objectPackageDisabledError docblock: 「The ONE refusal for an object whose owning package is disabled, raised by every API reader of that object … One constructor, so the two halves of the answer cannot drift apart in code, status or text.」
packages/rest/src/meta-item-read-gate.ts, createMetaLayeredAnswer step 1b: 「A disabled package's item — every type the by-name read withholds for it — is that same absent: the list read omits it and the by-name read answers it as a name with nothing behind it, so both spellings on both transports take the missing name's exit. … An object is the protocol's own OBJECT_PACKAGE_DISABLED refusal, thrown by the read before this chain; which other types are hidden is the plain read's decision, never restated here.」 Step 1 cites ADR-0045 §3: 「"Hidden" means externally unobservable, consistently across every surface」.
ADR-0112 D3: 「adding a service code touches the service's own ledger entry, not the spec enum — but it is still a deliberate, reviewable act, which is the entropy gate this whole problem lacked.」
The protocol already decided this per type, in one place, and recorded it in its own docblocks and in REST's read gate: an object of a disabled package is refused loudly, OBJECT_PACKAGE_DISABLED, because it has a data plane; every other item, an action included, is hidden — answered as a name with nothing behind it, on both transports, byte for byte. The /actions door is one more reader of that item; its disagreement with GET /meta/action/NAME and with MCP is the two-implementations case 元判据② names, and the governed side (the protocol's read, which carries the disable predicate) wins. The card's two asks conflict only if 「the same coded answer」 is read as the code's spelling; read as 「the answer the same read gives」, the Shape holds whole. No floor moves: the door narrows (a served 200 becomes the door's existing 404, the same class and changeset shape as PR #25305), no permission boundary moves, no contract entry is rewritten or added, no gate is loosened and none is added. A PM answer, not an escalation.
Why not A. It needs a second constructor of the refusal in the runtime, which #25296's own docblock forbids (「never a second copy of the package predicate or of the refusal」), under a code whose registered meaning is 「object is registered but its owning package is disabled」 and a message naming an object the caller never addressed — the misnaming the ledger's *_DISABLED comment rejects (an operator sent hunting an object that is not the thing that is off). And it makes an action the protocol hides observable through one door, against step 1b and ADR-0045 §3.
Why not C. A new ledger row is a packages/spec contract edit (ADR-0112 D3: a deliberate act of its own; 〈升级与决策〉: 「改协议单独立卡,⛔ 不作缺陷卡的选项」), cross-lane, for a code that would contradict the protocol's hidden-as-absent decision on the same declaration: GET /meta/action/NAME would say the name does not exist while POST /actions/global/NAME would say which package owns it. Zero pull: no consumer branches on a package-disabled code for an action; the only consumer-visible need is that the handler stops running, which B delivers. (ACTION_DISABLED is not an option either: ADR-0126's 409 is for a declared, listed action this installation switched off through the activation ledger; a disabled package's action is listed nowhere.)
Fixed here, so the PR opens no second decision on the same point:
The answer. For the object-less arm, an action whose owning package is disabled resolves to no declaration, and the door answers the ADR-0110 D3 404 it already answers an undeclared name — same status, same RESOURCE_NOT_FOUND envelope code, same message text, nothing added. ⛔ No 「disabled」 hint in the message, no package code, no new code, no new message: the answer must not be distinguishable from the missing name's (ADR-0045 §3, step 1b). Both spellings (global and the empty segment) take it.
The read, and no second copy. The standalone-declaration sources of resolveRouteActionDeclaration (today: the registry's getItem('action', name), then the metadata service's loadDiagnosed / load) are read through the protocol's by-name read on a host whose protocol slot has one, in the shape readExposureDeclaration already uses (getMetaItemForExecution, else getMetaItem; the request { type: 'action', name }; an envelope whose item is absent or carries another name is no declaration from that source; the ownsRoute check stays). The registry and metadata-service sources remain only where the slot has no by-name read (a host without a protocol; test doubles), as readExposureDeclaration falls back to the copy. ⛔ No call to registry.isPackageDisabled / isObjectPackageDisabled from the runtime, no _packageId inspection, no copy of isItemOfDisabledPackage: the withholding is the protocol's, and the door reads its answer. The execution face is the right one here: the door dispatches on the declaration and serves the handler's result, never the declaration (the execution-face docblock: 「a gate inside such a door may read a DECISION off it」), and the registry item it replaces is served to no one today either.
Reach. The one read serves both arms' standalone declarations. The object-scoped arm's disabled OBJECT keeps rest: POST /api/v1/actions/OBJECT/NAME runs a disabled package's script action (200, the handler's answer) while the data plane refuses its object 404 OBJECT_PACKAGE_DISABLED #25296's 404 OBJECT_PACKAGE_DISABLED (asked first, unchanged, its pins stay green). A standalone action of a disabled package bound to an ENABLED object of another package is the same hidden item and takes the same D3 404: pin it on one shape if the rig makes it cheaply, else record it in the report as derived, not pinned. Object-embedded actions (source 1) are untouched. collectActionDeclarations, resolveActionByName, refuseAmbiguousActionActivation and domains/mcp.ts are not this card's (claim 6353642578).
Pins (the card's ask, extended by item 1): both kernel shapes, both spellings; the disabled package's object-less script action answers 404 with the handler never called and the engine never reached; the answer's status, envelope code and message equal those of an undeclared object-less name on the same shape (the hidden-equals-missing control); an enabled-package control runs 200; an environment-authored object-less action still runs (the mcp: a package's object-less (global) action is invisible to list_actions / run_action on every kernel shape, while REST's POST /api/v1/actions/global/NAME runs it #25297 rig's control); after enablePackage the action runs again; the anonymous 401 baseline still answers first. Red at base, green at head, ablation of the read restored from HEAD.
Premise, falsifiable, checked before the edit: at the PR's base, GET /api/v1/meta/action/NAME serves every object-less action the registry and metadata-service sources resolve for the door while its package is enabled (manifest-registered, compiled-artifact, environment-authored), on both shapes — the card's own measurement at ee2cd6e78b holds this for the package's action. A base where an enabled, declared action the old sources resolve is absent from the protocol's by-name read falsifies it: stop and report the fork on this card, ⛔ do not keep both sources 「to be safe」 (that re-opens the defect for whatever the registry holds), ⛔ do not switch to A or C.
Why B, on the four axes (business standpoint)
① Long-term soundness (weight ≥50%). Two years out, disabling a package takes everything it ships off every door by one rule, decided once in the protocol per type and read everywhere else — the way the major platforms hide an uninstalled app's actions rather than naming the app in every refusal. B makes the /actions door read that decision; A and C each put a second statement of it in the runtime or the ledger, and C makes two doors disagree about whether the name exists.
③ AI-error prevention. An AI author or agent that probes /actions/global/NAME on a disabled package sees exactly what it sees for a typo: one refusal class, closed, the same the metadata API already teaches; it cannot learn package membership from an action door. A's message would teach that an action 「is an object」; C would teach a code the metadata API contradicts. Failure stays loud: a disabled package's action that still runs is a red pin, and a protocol outage is a 503, never a silent run.
④ Startup no-sprawl. No new code, no ledger row, no spec edit, no new gate; one read moved to the protocol's face in one function, one pin file extended, one changeset.
Only-① pick: B. Do ②③④ flip it: no. Effort for the chosen letter: one PR on the card's claimed surface (actions.ts / action-execution.ts / the #25296 pin file / one changeset), the shape of PR #25305; nothing cross-lane.
os-decision-facets
① 长远:B 让 /actions 门读协议已按类型裁定的「禁用即隐藏」答案,契约不增生;A 在运行时另造一份对象码的拒绝,C 在台账加一行并让两扇门对同一声明说相反的话。
② 拉动:缺陷两种内核实测(卡面、#25305 合同记录 3.1);无人消费动作的「包禁用」码,GET /meta/action 与 MCP 早已答「不存在」;拉动只是「别再执行」,B 零新词汇兑现。
③ 防错:禁用包的动作与打错的名字得到同一类响亮 404,闭合枚举,不泄露包归属;协议读挂掉答 503 而非静默执行;A 教 AI「动作是对象」,C 教一个与元数据 API 自相矛盾的码。
④ 不扩散:不加码、不改 spec、不加门禁;一处读改走协议面、一份 pin 文件扩展、一份 changeset。
Prior rulings read: disabled,package,global,object-less,object_package_disabled,resource_not_found,withheld,absent → 102 hits; ADR-0068 D3, ADR-0081 Decision §3, ADR-0087 D1, ADR-0003 Decision §1-§4, ADR-0005 Decision §5 (term noise on package / disabled / global; ADR-0003 §4 names the installation's disabled status and decides no door's answer; none decides a disabled package's action answer, read); thread: none by the script's first-line shape (read by hand: 6353592171, 6353642578); other records: #252966353106465, PR #253056353092142, PR #253046353066024; repo: objectstack-ai/objectstack
Execution after the ruling
Thread-read: 6353642578 (the newest comment on this card at this write). The card thread continues as claimed there, on letter B as it already started; its next comment on this card carries Ruling-ref: this comment's id at line start.
⛔ Ruling is not dispatching; the thread already holds its slot and the card stays pm:dispatched. No decision card to the maintainer; this comment is the record, reversible on one word.
Cross-lane: none. No packages/spec, no ledger row, no gate, no script edit.
{
"issue": 25308,
"status": "done",
"branch": "claude/project-thread-vlqmr4",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25318",
"head": "836c23e3eee88ac4b0a1e6dd62f19f21b8dc7cfe",
"session": "session_013txgcKJ9EWEZJhQ41e7kZg",
"premise_still_valid": true,
"ruling": "6353801421 (letter B), implemented as written: items 1 to 7",
"summary": "resolveRouteActionDeclaration (action-execution.ts) now reads a standalone action declaration through the protocol's by-name action read in readExposureDeclaration's shape (getMetaItemForExecution, else getMetaItem; { type: 'action', name }; the item under its own name or nothing; ownsRoute kept), after the object's embedded actions and in place of the registry and metadata-service copies, which stay only for a host whose protocol has no by-name read. That read withholds a disabled package's item, so POST /api/v1/actions/global/NAME and /actions//NAME (and an enabled object's route, and the package's action bound to an enabled package's object) answer the existing ADR-0110 D3 'no declaration' 404, byte-identical but for the name to a name nothing declares. A throwing read is degraded, the existing 503, never a copy. No runtime isPackageDisabled or _packageId read; domains/actions.ts unchanged. Premise measured at base 258f4e6aa on both kernel shapes: 200 with the handler's result.",
"precondition_item_7": "Measured before the change, scratch probe on both shapes: with every package enabled, getMetaItemForExecution and getMetaItem both served under its own name every standalone action the old sources resolved (manifest-registered object-less and bound, environment-authored, a compiled artifact's project action and its packages[] entry's), and REST answered each 200. No fork raised.",
"tests": "packages/runtime/src/domains/actions-disabled-package.test.ts extended from 24 to 50 cases on real kernels (env_local with createStandaloneStack's options, and no environmentId), through HttpDispatcher.dispatch(): ENABLED control (package and authored object-less actions 200 on both spellings; an undeclared object-less name the D3 404) and DISABLED package (protocol read withholds the package's action and serves the authored one; on both spellings, on an enabled object's route, and for the action bound to the enabled side package's object, the answer equals the qa_nowhere answer in status, code and message with the name removed, handler never called, getData/updateData/executeAction never reached; authored action still 200; anonymous 401; after enablePackage it runs again). Red/green under the verify lock: main leg (base action-execution.ts and actions.ts restored into the worktree, then git checkout HEAD, diff empty) 8 failed / 42 passed, the four leak cases on both shapes each 'expected 200 to be 404'; ablation via scripts/ablation-replace.mjs (if (byName) { to if (byName && false) {, blob e4eebd83e059 to 271f6b423b30, restored blob equals HEAD) 8 failed / 42 passed; fix 50 passed. @objectstack/runtime test VERDICT command-exit 0: Test Files 437 passed, Tests 7019 passed, 19 skipped (7038). runtime typecheck and eslint --no-inline-config VERDICT command-exit 0.",
"gates": "Local on 836c23e3: dispatch-gates --commands 68 derived, each run, every one exit 0 (check:type-check-debt under the lock); --ran on the cmd-exit record: 68 derived, 68 run, 0 NOT-MEASURED, a DERIVED zero. CI on 836c23e3: 41 check-runs, every one completed, success or skipped by design (opt-in and path-filtered jobs), 0 failure; Test Core and its six shards, Build Core, Lint and Repo Gates, TypeScript Type Check, Check Changeset, Governed Surface Queue Guard all success.",
"dogfood_battery": "836c23e3eee88ac4b0a1e6dd62f19f21b8dc7cfe · PR comment 6354539283 · os-verify-lock: VERDICT command-exit 0 · held the lock 1017s (16m57s) · Test Files 289 passed, 3 skipped (292) · Tests 2491 passed, 18 skipped (2509) · 0 failed",
"contract_review": "PR comment 6354656372 · Served-tier CONTRACT_REVIEW_TIER · face narrowing · Head-sha 836c23e3ee · Local-runs none · VERDICT PASS · rendered by an isolated read-only reviewer at that tier with zero writes, posted by this session through the relay",
"mcp_calls": "reads only, 0 writes: issue_read get and get_comments on #25308; pull_request_read get_check_runs and get_status on #25318; the reviewer's reads of #25308 and #25318",
"api_writes": "all through scripts/pm/ on the fleet-write dispatch transport, each read back identical: the claim stroke (label-write) and claim comment 6353642578 (post-stamped); pr_create #25318 with assignee os-sales and pr_request_reviewers os-sales (dispatch.mjs); dogfood_battery comment 6354539283 and contract record 6354656372 on #25318 (post-stamped); this report",
"deviations": [
"File surface narrower than claimed: domains/actions.ts is unchanged in the net diff (the ruling moved the mechanism into resolveRouteActionDeclaration). The branch carries an interim _packageId implementation (57b21c61) written before the ruling arrived and reverted by e30b5e80; the squash carries only the protocol read.",
"The activation door (POST /actions/_activation/OBJECT/NAME) resolves through the same function, so a disabled package's standalone action now answers that door's own 'no declaration' 404 where a flip wrote a ledger row before. Declared in the changeset's Also bullet and the PR's Contract item 6; derived, not pinned. The reviewer confirmed an enabled package's action still carries _packageId through the protocol read, so shippingPackageOf writes the same ledger row as before.",
"The 503 on a throwing protocol read (ruling item 3) is by construction, not pinned: no real-kernel rig here makes that read throw.",
"Branch claude/project-thread-vlqmr4 is the name the session was given, not claude/issue-25308-*; the claim names it."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: a stored action row whose body omits name would stop resolving on a protocol host, because the new item.name === actionName check (ruling item 2) is stricter than the old registry and metadata rungs and storedRowDocument does not fold the row's name column into the body · evidence: contract record 6354656372 boundary flag, read in item-lock.ts; no such row was measured in any rig (every saveMetaItem path in the pins and the probe carries name) · dedupe words: stored action row body without name by-name read · carrier: none, recorded for the seat's judgment; filing only if such rows are shown to exist"
]
}
Activity
objectstack-fleet commentedon Oct 22, 2026
Unblocked ·
domain:cliseat 1 · sessionsession_01CxBKycaiUpA1yGx1XyoGqX· 2026-10-22T23:27ZBlocked-by: #25296target is closedcompleted(PR #25305 merged as squash258f4e6aa, an ancestor oforigin/main). Re-derived: no new blocker. PR #25305 addedrefuseDisabledPackageObjectfor the object-scoped arm ofdomains/actions.tsand skippedisObjectLessActionKeykeys by design; this card's object-less arm has no other open dependency. PR #25304 (#25297) has also landed (882372d79), so MCP already omits a disabled package's object-less action; this card brings REST level with it.pm:blocked→pm:queuein this act.Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
Claim: card thread, Sales-account project (
domain:cli)Session:
session_013txgcKJ9EWEZJhQ41e7kZgAccount:
os-salesBranch:
claude/project-thread-vlqmr4Worktree:
objectstack-issue-25296(dedicated cloud container, not a shared checkout; the branch carried PR #25305 for #25296 until it merged as258f4e6aa, and restarts fromorigin/main258f4e6aafor this card)Domain:
domain:cliSeat:
domain:cli#1(the card thread of seat 1, seat post #6024; 由Sales账户的项目负责)File surface:
packages/runtime/src/domains/actions.ts(the/actionsdoor's object-less arm),packages/runtime/src/action-execution.ts(besiderefuseDisabledPackageObject/resolveRouteActionDeclaration; nothing incollectActionDeclarations/resolveActionByName),packages/runtime/src/domains/actions-disabled-package.test.ts(#25296's pin file, extended), one.changeset/*.md(stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT(no path-derived mandate on the two runtime files; ceilingCONTRACT_REVIEW_TIER, reason: the measured diff narrows, which owes one review at that tier before the queue),effort: highClause-②: no (narrowing)
Metadata-protocol: none
Responsibility:
packages/runtime's/actionsdoor resolves an object-less action from the engine registry'sactionitem, which still holds a disabled package's item, and skips the object-scoped refusal #25296 added because the route names no object | the protocol's by-name action read (getMetaItem/getMetaItemForExecution,GET /api/v1/meta/action/NAME's read) withholds a disabled package's item, and the MCP bridge (PR #25304) answers it "not found"; the door never asks that read | every REST / SDK caller ofPOST /api/v1/actions/global/NAMEorPOST /api/v1/actions//NAMEon an installation with a disabled packageThread-read: 6353592171
Serial constraints cleared: PR #25305 (#25296, the same file) merged
258f4e6aa; PR #25304 (#25297,action-execution.ts's collection) merged882372d79; MCPsearch_pull_requestsfor open PRs namingactions.ts,action-executionor/actionsfound none on this surface at claim time.Clause-② reading, provisional until measured: a disabled package's object-less action stops running on the REST door (a served
200refused: narrowing). The coded answer is not settled by the card's Shape, which asks both for #25296's code and for the same package-disabled read with no second copy: for anactionitem that read withholds the item (absence) and raises noOBJECT_PACKAGE_DISABLED. That choice goes to the coordinator asneeds_decisionwith options before the PR; measurement and the pins proceed meanwhile.Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
Ruling: needs_decision fork review (project review thread 「#25308 错误码裁决」) · letter B · maintainer 「对于这种类似的问题,能否你自己开一个单独的 fable thread 做评审,对于自己有把握决定的问题,自己决定,不能决定的开决策卡?」 2026-10-22T23:43Z
Proxy ruling under the maintainer's delegation quoted above (carried into this project by its owner's standing rule 「卡线程报 needs_decision 时,另开 fable 裁决线程,有把握就裁并把裁决落在 GitHub 上,没把握才给 Bill 发决策卡」), by the review thread's session⚠️ Reversible on one word from the maintainer; nothing here forecloses that.
session_01XTZeM6mzPjShD3uSvT5T9d(project thread), on thedomain:cliseat 1 card thread's needs_decision fork (claim6353642578, sessionsession_013txgcKJ9EWEZJhQ41e7kZg, which records 「The coded answer is not settled by the card's Shape … That choice goes to the coordinator as needs_decision with options before the PR」). The card thread's next comment here carriesRuling-ref:this comment's id. Marker:auto-adjudicated.The question
The card's Shape asks two things at once of the object-less arm (
POST /api/v1/actions/global/NAME,POST /api/v1/actions//NAME): 「with the same coded answer #25296 chooses」 (404 OBJECT_PACKAGE_DISABLED) and 「reusing the same package-disabled read (⛔ not a second copy)」. Read atmain258f4e6aa, both cannot hold at once: the protocol's by-name read of anactionitem never raisesOBJECT_PACKAGE_DISABLED.readMetaItemFace(packages/metadata-protocol/src/protocol.ts) throwsobjectPackageDisabledErroronly whenrequest.type === 'object'; for every other type butpackageit answers a disabled package's item as an envelope with noitem, the missing name's answer; and the one constructor takes an object name and saysObject '…' belongs to a disabled package. The options the card thread laid out:404 OBJECT_PACKAGE_DISABLEDliterally: the runtime builds its own refusal for an action (a second constructor, an object code and an object message on a thing that is not an object).GET /api/v1/meta/action/NAMEanswers404 RESOURCE_NOT_FOUNDand the MCPrun_actionbridge answersAction 'NAME' not foundsince PR fix(runtime)!: the /mcp bridge's list_actions, run_action and resume_run read the actions no object embeds from the merged action listing, so a package's object-less action and an environment-authored one are listed and run #25304.ACTION_PACKAGE_DISABLEDinpackages/spec/src/api/error-code-ledger.zod.tsand raise it from the door.This thread's reading at
main258f4e6aareadMetaItemFace(protocol.ts, the one body behindgetMetaItemandgetMetaItemForExecution): an object of a disabled package → throwobjectPackageDisabledError(name); any other type whose resolved itemisItemOfDisabledPackage→{ ...envelope, item: undefined }withregistrationdropped (draft state →404 NO_DRAFT). The constructor's message:Object '${object}' belongs to a disabled package and is not being served. Re-enable the package to restore access., withcode OBJECT_PACKAGE_DISABLED,status 404,object.error-code-ledger.zod.ts):'OBJECT_PACKAGE_DISABLED', // [#7557] object is registered but its owning package is disabled — data plane refuses rather than serving rows. No*_PACKAGE_DISABLEDrow names an action. The*_DISABLEDfamily comment besideACTION_DISABLED(ADR-0126 §8 item 2, the activation ledger's 409 for a declared, listed action this installation switched off) reads: 「each names WHICH thing is off, which is what an operator acts on」 and 「ascriptaction refused under a code naming a flow sends an operator hunting a flow that does not exist」.resolveRouteActionDeclaration(packages/runtime/src/action-execution.ts): source 1 the object's ownactions[], source 2ql.registry.getItem('action', name), source 3 the metadata service'sloadDiagnosed('action', name); a miss →{ action: undefined }and the door's ADR-0110 D3 「has no declaration」 404 (deps.error(…, 404), whose envelope code is the status'sRESOURCE_NOT_FOUND,packages/spec/src/api/errors.zod.tsline 187); an outage →degradedand the 503. The registry still holds a disabled package'sactionitem, which is the defect: only the protocol's own reads applyisItemOfDisabledPackage.refuseDisabledPackageObject(rest: POST /api/v1/actions/OBJECT/NAME runs a disabled package's script action (200, the handler's answer) while the data plane refuses its object 404 OBJECT_PACKAGE_DISABLED #25296, the same file): reads the object throughreadExposureDeclaration(getMetaItemForExecution, elsegetMetaItem, else the metadata service's copy) and rethrows only the protocol's own refusal; its docblock: 「⛔ never a second copy of the package predicate or of the refusal. Any other answer of that read is not this gate's to give: an absent object is the declaration resolution's to answer」./metadoor on a disabled package's item:packages/runtime/src/domains/meta-disabled-package-doors.test.tspins 「a disabled package's item is absent, byte for byte the answer for a missing name」 (apage: status 404, codeRESOURCE_NOT_FOUND,JSON.stringifyof the two bodies equal). For anaction, the card and rest: POST /api/v1/actions/OBJECT/NAME runs a disabled package's script action (200, the handler's answer) while the data plane refuses its object 404 OBJECT_PACKAGE_DISABLED #25296's report measuredGET /api/v1/meta/action/NAMEanswering404 RESOURCE_NOT_FOUNDafter the disable, on both shapes. MCP since PR fix(runtime)!: the /mcp bridge's list_actions, run_action and resume_run read the actions no object embeds from the merged action listing, so a package's object-less action and an environment-authored one are listed and run #25304:run_actionanswersAction 'NAME' not found/… not found on object 'global'for the disabled package's object-less action and still runs the environment-authored one (mcp-package-object-discovery.test.ts, the mcp: a package's object-less (global) action is invisible to list_actions / run_action on every kernel shape, while REST's POST /api/v1/actions/global/NAME runs it #25297 blocks, both kernel shapes).6353106465,out_of_scope_findings) read the cause the same way: 「resolveRouteActionDeclarationreads the registry's standalone action item, whichisItemOfDisabledPackagehides only inside the protocol's own /meta reads; the likely owed answer is the no-declaration 404」.Governing text, read at
main258f4e6aagetMetaItemdocblock: 「[Package disable and uninstall never reach the metadata/data layer: a disabled package's objects still serve rows, and uninstall leaves 7 orphanedsys_metadatarows #7557, metadata-protocol: a by-name /meta read of a non-object item (app, view, page, …) serves a disabled package's item while the list omits it; #24097 closes the object half only #24210] Every other type butpackagehas no data plane, so a disabled package's item is answered as ABSENT, the answer a name with nothing behind it gets: the list read omits that item, by the same predicate ({@link isItemOfDisabledPackage}) asked of the item this read resolved, in every state. … The other reads serve noitem, which both transports answer404 RESOURCE_NOT_FOUND, byte for byte the missing name's answer」.isItemOfDisabledPackagedocblock: 「The ONE predicate for a non-object item, asked by the list read … and the by-name read …, so the two cannot disagree about which items a disable hides.」;objectPackageDisabledErrordocblock: 「The ONE refusal for an object whose owning package is disabled, raised by every API reader of that object … One constructor, so the two halves of the answer cannot drift apart in code, status or text.」packages/rest/src/meta-item-read-gate.ts,createMetaLayeredAnswerstep 1b: 「A disabled package's item — every type the by-name read withholds for it — is that sameabsent: the list read omits it and the by-name read answers it as a name with nothing behind it, so both spellings on both transports take the missing name's exit. … An object is the protocol's ownOBJECT_PACKAGE_DISABLEDrefusal, thrown by the read before this chain; which other types are hidden is the plain read's decision, never restated here.」 Step 1 cites ADR-0045 §3: 「"Hidden" means externally unobservable, consistently across every surface」..claude/skills/pm-dispatch/SKILL.md〈升级与决策〉: 「协议为基准:spec 与代码不一致默认改代码对齐;改协议单独立卡,⛔ 不作缺陷卡的选项。」; 「② 一个操作两个实现且行为不一致 ⇒ 带治理的一侧(权限闸、同意、去重、审计)胜出。另一侧改绑并删除,不是对齐也不是双写」; 「既有门禁内部参数与盲区修复(加强,非削弱,非新增)」; 「dev 的needs_decision经 PM 复核落进不升级类的,PM 直接答复不上传。」; 「裁决一次裁清:子问题、分叉与执行参数同笔裁定」.Ruling: B
The protocol already decided this per type, in one place, and recorded it in its own docblocks and in REST's read gate: an object of a disabled package is refused loudly,
OBJECT_PACKAGE_DISABLED, because it has a data plane; every other item, anactionincluded, is hidden — answered as a name with nothing behind it, on both transports, byte for byte. The/actionsdoor is one more reader of that item; its disagreement withGET /meta/action/NAMEand with MCP is the two-implementations case 元判据② names, and the governed side (the protocol's read, which carries the disable predicate) wins. The card's two asks conflict only if 「the same coded answer」 is read as the code's spelling; read as 「the answer the same read gives」, the Shape holds whole. No floor moves: the door narrows (a served 200 becomes the door's existing 404, the same class and changeset shape as PR #25305), no permission boundary moves, no contract entry is rewritten or added, no gate is loosened and none is added. A PM answer, not an escalation.Why not A. It needs a second constructor of the refusal in the runtime, which #25296's own docblock forbids (「never a second copy of the package predicate or of the refusal」), under a code whose registered meaning is 「object is registered but its owning package is disabled」 and a message naming an object the caller never addressed — the misnaming the ledger's
*_DISABLEDcomment rejects (an operator sent hunting an object that is not the thing that is off). And it makes an action the protocol hides observable through one door, against step 1b and ADR-0045 §3.Why not C. A new ledger row is a
packages/speccontract edit (ADR-0112 D3: a deliberate act of its own; 〈升级与决策〉: 「改协议单独立卡,⛔ 不作缺陷卡的选项」), cross-lane, for a code that would contradict the protocol's hidden-as-absent decision on the same declaration:GET /meta/action/NAMEwould say the name does not exist whilePOST /actions/global/NAMEwould say which package owns it. Zero pull: no consumer branches on a package-disabled code for an action; the only consumer-visible need is that the handler stops running, which B delivers. (ACTION_DISABLEDis not an option either: ADR-0126's 409 is for a declared, listed action this installation switched off through the activation ledger; a disabled package's action is listed nowhere.)Fixed here, so the PR opens no second decision on the same point:
RESOURCE_NOT_FOUNDenvelope code, same message text, nothing added. ⛔ No 「disabled」 hint in the message, no package code, no new code, no new message: the answer must not be distinguishable from the missing name's (ADR-0045 §3, step 1b). Both spellings (globaland the empty segment) take it.resolveRouteActionDeclaration(today: the registry'sgetItem('action', name), then the metadata service'sloadDiagnosed/load) are read through the protocol's by-name read on a host whoseprotocolslot has one, in the shapereadExposureDeclarationalready uses (getMetaItemForExecution, elsegetMetaItem; the request{ type: 'action', name }; an envelope whoseitemis absent or carries anothernameis no declaration from that source; theownsRoutecheck stays). The registry and metadata-service sources remain only where the slot has no by-name read (a host without a protocol; test doubles), asreadExposureDeclarationfalls back to the copy. ⛔ No call toregistry.isPackageDisabled/isObjectPackageDisabledfrom the runtime, no_packageIdinspection, no copy ofisItemOfDisabledPackage: the withholding is the protocol's, and the door reads its answer. The execution face is the right one here: the door dispatches on the declaration and serves the handler's result, never the declaration (the execution-face docblock: 「a gate inside such a door may read a DECISION off it」), and the registry item it replaces is served to no one today either.degraded: truewith the reason, so the door answers its existing 503. ⛔ Not a fall back to the registry copy on a throw — that would run a disabled package's action through an outage, the widening the mcp: list_objects / describe_object cannot see any package-installed object (a marketplace app's whole schema) — the HTTP bridge reads the metadata service, not the SchemaRegistry REST serves #25120 docblock forbids (「An outage of the merged read must not WIDEN exposure」).404 OBJECT_PACKAGE_DISABLED(asked first, unchanged, its pins stay green). A standalone action of a disabled package bound to an ENABLED object of another package is the same hidden item and takes the same D3 404: pin it on one shape if the rig makes it cheaply, else record it in the report as derived, not pinned. Object-embedded actions (source 1) are untouched.collectActionDeclarations,resolveActionByName,refuseAmbiguousActionActivationanddomains/mcp.tsare not this card's (claim6353642578).enablePackagethe action runs again; the anonymous 401 baseline still answers first. Red at base, green at head, ablation of the read restored from HEAD.fix(runtime)!,patch,Clause-②: no (narrowing),Metadata-protocol: none, ADR-0087not-required (no-migration-prescription), in PR fix(runtime)!: REST's /actions door refuses an action on an object whose owning package is disabled 404 OBJECT_PACKAGE_DISABLED, before any handler runs #25305's shape; the BREAKING sentence names the object-less arm;Fixes #25308alone. Nothing inpackages/spec, nothing inpackages/metadata-protocol, nothing inpackages/rest. Cross-lane: none.GET /api/v1/meta/action/NAMEserves every object-less action the registry and metadata-service sources resolve for the door while its package is enabled (manifest-registered, compiled-artifact, environment-authored), on both shapes — the card's own measurement atee2cd6e78bholds this for the package's action. A base where an enabled, declared action the old sources resolve is absent from the protocol's by-name read falsifies it: stop and report the fork on this card, ⛔ do not keep both sources 「to be safe」 (that re-opens the defect for whatever the registry holds), ⛔ do not switch to A or C.Why B, on the four axes (business standpoint)
/actionsdoor read that decision; A and C each put a second statement of it in the runtime or the ledger, and C makes two doors disagree about whether the name exists.GET /meta/action/NAMEhas answered the missing name's 404 since metadata-protocol: a by-name /meta read of a non-object item (app, view, page, …) serves a disabled package's item while the list omits it; #24097 closes the object half only #24210, MCP answers 「not found」 since fix(runtime)!: the /mcp bridge's list_actions, run_action and resume_run read the actions no object embeds from the merged action listing, so a package's object-less action and an environment-authored one are listed and run #25304, and no client branch reads such a code. The pull is 「stop running it」, which every letter delivers; only B delivers it with zero new vocabulary./actions/global/NAMEon a disabled package sees exactly what it sees for a typo: one refusal class, closed, the same the metadata API already teaches; it cannot learn package membership from an action door. A's message would teach that an action 「is an object」; C would teach a code the metadata API contradicts. Failure stays loud: a disabled package's action that still runs is a red pin, and a protocol outage is a 503, never a silent run.Only-① pick: B. Do ②③④ flip it: no. Effort for the chosen letter: one PR on the card's claimed surface (
actions.ts/action-execution.ts/ the #25296 pin file / one changeset), the shape of PR #25305; nothing cross-lane.os-decision-facets
① 长远:B 让 /actions 门读协议已按类型裁定的「禁用即隐藏」答案,契约不增生;A 在运行时另造一份对象码的拒绝,C 在台账加一行并让两扇门对同一声明说相反的话。
② 拉动:缺陷两种内核实测(卡面、#25305 合同记录 3.1);无人消费动作的「包禁用」码,GET /meta/action 与 MCP 早已答「不存在」;拉动只是「别再执行」,B 零新词汇兑现。
③ 防错:禁用包的动作与打错的名字得到同一类响亮 404,闭合枚举,不泄露包归属;协议读挂掉答 503 而非静默执行;A 教 AI「动作是对象」,C 教一个与元数据 API 自相矛盾的码。
④ 不扩散:不加码、不改 spec、不加门禁;一处读改走协议面、一份 pin 文件扩展、一份 changeset。
Prior rulings read: disabled,package,global,object-less,object_package_disabled,resource_not_found,withheld,absent → 102 hits; ADR-0068 D3, ADR-0081 Decision §3, ADR-0087 D1, ADR-0003 Decision §1-§4, ADR-0005 Decision §5 (term noise on
package/disabled/global; ADR-0003 §4 names the installation'sdisabledstatus and decides no door's answer; none decides a disabled package's action answer, read); thread: none by the script's first-line shape (read by hand:6353592171,6353642578); other records: #252966353106465, PR #253056353092142, PR #253046353066024; repo: objectstack-ai/objectstackExecution after the ruling
6353642578(the newest comment on this card at this write). The card thread continues as claimed there, on letter B as it already started; its next comment on this card carriesRuling-ref:this comment's id at line start.pm:dispatched. No decision card to the maintainer; this comment is the record, reversible on one word.packages/spec, no ledger row, no gate, no script edit.objectstack-fleet commentedon Oct 23, 2026
os-dev-report
Ruling-ref: 6353801421
{ "issue": 25308, "status": "done", "branch": "claude/project-thread-vlqmr4", "pr": "https://github.com/objectstack-ai/objectstack/pull/25318", "head": "836c23e3eee88ac4b0a1e6dd62f19f21b8dc7cfe", "session": "session_013txgcKJ9EWEZJhQ41e7kZg", "premise_still_valid": true, "ruling": "6353801421 (letter B), implemented as written: items 1 to 7", "summary": "resolveRouteActionDeclaration (action-execution.ts) now reads a standalone action declaration through the protocol's by-name action read in readExposureDeclaration's shape (getMetaItemForExecution, else getMetaItem; { type: 'action', name }; the item under its own name or nothing; ownsRoute kept), after the object's embedded actions and in place of the registry and metadata-service copies, which stay only for a host whose protocol has no by-name read. That read withholds a disabled package's item, so POST /api/v1/actions/global/NAME and /actions//NAME (and an enabled object's route, and the package's action bound to an enabled package's object) answer the existing ADR-0110 D3 'no declaration' 404, byte-identical but for the name to a name nothing declares. A throwing read is degraded, the existing 503, never a copy. No runtime isPackageDisabled or _packageId read; domains/actions.ts unchanged. Premise measured at base 258f4e6aa on both kernel shapes: 200 with the handler's result.", "precondition_item_7": "Measured before the change, scratch probe on both shapes: with every package enabled, getMetaItemForExecution and getMetaItem both served under its own name every standalone action the old sources resolved (manifest-registered object-less and bound, environment-authored, a compiled artifact's project action and its packages[] entry's), and REST answered each 200. No fork raised.", "tests": "packages/runtime/src/domains/actions-disabled-package.test.ts extended from 24 to 50 cases on real kernels (env_local with createStandaloneStack's options, and no environmentId), through HttpDispatcher.dispatch(): ENABLED control (package and authored object-less actions 200 on both spellings; an undeclared object-less name the D3 404) and DISABLED package (protocol read withholds the package's action and serves the authored one; on both spellings, on an enabled object's route, and for the action bound to the enabled side package's object, the answer equals the qa_nowhere answer in status, code and message with the name removed, handler never called, getData/updateData/executeAction never reached; authored action still 200; anonymous 401; after enablePackage it runs again). Red/green under the verify lock: main leg (base action-execution.ts and actions.ts restored into the worktree, then git checkout HEAD, diff empty) 8 failed / 42 passed, the four leak cases on both shapes each 'expected 200 to be 404'; ablation via scripts/ablation-replace.mjs (if (byName) { to if (byName && false) {, blob e4eebd83e059 to 271f6b423b30, restored blob equals HEAD) 8 failed / 42 passed; fix 50 passed. @objectstack/runtime test VERDICT command-exit 0: Test Files 437 passed, Tests 7019 passed, 19 skipped (7038). runtime typecheck and eslint --no-inline-config VERDICT command-exit 0.", "gates": "Local on 836c23e3: dispatch-gates --commands 68 derived, each run, every one exit 0 (check:type-check-debt under the lock); --ran on the cmd-exit record: 68 derived, 68 run, 0 NOT-MEASURED, a DERIVED zero. CI on 836c23e3: 41 check-runs, every one completed, success or skipped by design (opt-in and path-filtered jobs), 0 failure; Test Core and its six shards, Build Core, Lint and Repo Gates, TypeScript Type Check, Check Changeset, Governed Surface Queue Guard all success.", "dogfood_battery": "836c23e3eee88ac4b0a1e6dd62f19f21b8dc7cfe · PR comment 6354539283 · os-verify-lock: VERDICT command-exit 0 · held the lock 1017s (16m57s) · Test Files 289 passed, 3 skipped (292) · Tests 2491 passed, 18 skipped (2509) · 0 failed", "contract_review": "PR comment 6354656372 · Served-tier CONTRACT_REVIEW_TIER · face narrowing · Head-sha 836c23e3ee · Local-runs none · VERDICT PASS · rendered by an isolated read-only reviewer at that tier with zero writes, posted by this session through the relay", "mcp_calls": "reads only, 0 writes: issue_read get and get_comments on #25308; pull_request_read get_check_runs and get_status on #25318; the reviewer's reads of #25308 and #25318", "api_writes": "all through scripts/pm/ on the fleet-write dispatch transport, each read back identical: the claim stroke (label-write) and claim comment 6353642578 (post-stamped); pr_create #25318 with assignee os-sales and pr_request_reviewers os-sales (dispatch.mjs); dogfood_battery comment 6354539283 and contract record 6354656372 on #25318 (post-stamped); this report", "deviations": [ "File surface narrower than claimed: domains/actions.ts is unchanged in the net diff (the ruling moved the mechanism into resolveRouteActionDeclaration). The branch carries an interim _packageId implementation (57b21c61) written before the ruling arrived and reverted by e30b5e80; the squash carries only the protocol read.", "The activation door (POST /actions/_activation/OBJECT/NAME) resolves through the same function, so a disabled package's standalone action now answers that door's own 'no declaration' 404 where a flip wrote a ledger row before. Declared in the changeset's Also bullet and the PR's Contract item 6; derived, not pinned. The reviewer confirmed an enabled package's action still carries _packageId through the protocol read, so shippingPackageOf writes the same ledger row as before.", "The 503 on a throwing protocol read (ruling item 3) is by construction, not pinned: no real-kernel rig here makes that read throw.", "Branch claude/project-thread-vlqmr4 is the name the session was given, not claude/issue-25308-*; the claim names it." ], "open_questions": [], "out_of_scope_findings": [ "class: b · reach: a stored action row whose body omits name would stop resolving on a protocol host, because the new item.name === actionName check (ruling item 2) is stricter than the old registry and metadata rungs and storedRowDocument does not fold the row's name column into the body · evidence: contract record 6354656372 boundary flag, read in item-lock.ts; no such row was measured in any rig (every saveMetaItem path in the pins and the probe carries name) · dedupe words: stored action row body without name by-name read · carrier: none, recorded for the seat's judgment; filing only if such rows are shown to exist" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
ACCEPT → PR #25318 comment 6354693152 ·
domain:cliseat 1 · sessionsession_01CxBKycaiUpA1yGx1XyoGqX· 2026-10-23T00:50ZGenerated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
Landed ·
domain:cliseat 1 · sessionsession_01CxBKycaiUpA1yGx1XyoGqX· 2026-10-23T01:17Zmerged: true, merge commiteee2f0d4e, merged 2026-10-23T01:16:29Z through the merge queueorigin/maineee2f0d4eis an ancestor oforigin/main, single parent (squash)gh-readonly-queue/main/*head for PR 25318 remainsState: card closed
completedbyFixes #25308;pm:dispatchedstripped in this act.Generated by Claude Code