Repository navigation
meta: GET /meta/object serves which packaged actions are switched off beside the item, and the disabled-action refusal reads as a plain sentence #27842
Description
director#1 · os-bill · session_01Utp6CbNFJEooRTBtezEt7
Filing gate: (a) a reachable defect, the serve half of #27504, split out by a maintainer ruling (③: the maintainer's word 「同意」, 2026-10-30T01:35Z, on the brief recommending this split; the ruling comment of record is 6512814276 on #27504, letter B). reach: the public metadata read GET /api/v1/meta/object/:name (and the GET /api/v1/meta/object list) on a deployment whose administrator switched a packaged action off in Setup › Packaged automation: the read serves the action in actions[] with nothing beside it saying it is off, while POST /api/v1/actions/... for the same action is refused 409 ACTION_DISABLED. Measured by the 18.3.0 release-candidate walkthrough on examples/app-showcase (#27504, showcase_mark_done on showcase_task, framework main @ c4c515ad). Reader who acts: the domain:spec seat (lane fixed by the ruling); triage grades the level. ⛔ Not a claim.
Unblocks: #27504 (the console half: hide the button from this key; stays domain:ui, seat 4).
Ruling-ref: #27504 (comment) (letter B).
What happens
- A packaged action switched off in the
sys_metadata_activationledger (ADR-0126 §4, §8 item 2) is refused at both dispatch doors with the sentencedescribeDisabled()builds inpackages/objectql/src/action-activation.ts:297-303: it names the ledger table and an ADR section, and is what an end user reads in a red toast. - The metadata reads that every client builds its action buttons from (
GET /meta/object/:name,GET /meta/object) carry no activation fact at all. The only read of the fact is the generic data list of the ledger object (apiMethods: ['get','list'],packages/platform-objects/src/system/sys-metadata-activation.object.ts:192-197), which the Setup page joins client-side (ui/packages/app-shell/src/views/setup/packagedActions.ts). Every other consumer (the console record page, MCP agents, the SDK) sees the action as live. - Removing the action from the served
actions[]is not an option (the Setup page lists from it to offer the re-enable switch); rewritingvisible/disabledinside the item rides the GET → edit → PUT round trip back into the stored body.
Wanted
The #23316 shape (registration, PR #23358), as the action twin:
- Item read, both doors. A key beside
itemonGetMetaItemResponseSchemaand onGetMetaItemCachedResponseSchema(packages/spec/src/api/protocol.zod.ts, theregistrationmembers at L682 and L2318–2331 are the template) naming the packaged actions of this object that are switched off for this deployment. Published by the cached default door too; never part of the ETag, so a read that carries it is never answered 304 (the automation: a stored flow the engine refuses at cold boot is withdrawn with a warn, while the metadata read keeps serving it asstatus: 'active'— after the v18 upgrade, every refused flow reads as running #23316 trade, stated in the docblock). Present only when a process with an activation ledger answered; absent means "no ledger answered", never "nothing is switched off", so a consumer that sees no key keeps today's behaviour. - List. A name-keyed sibling of
itemson the object list, theregistrationspattern (L326). - The read seam. The metadata protocol reaches the engine's action-activation projection through the kernel service table, the way
getFlowRegistration?was declared optional onIAutomationServicein@objectstack/spec/contracts(PR fix(automation,metadata-protocol,rest,spec): a stored flow the engine refuses is served beside its verdict, not as running #23358 "The seam"). Which contract carries the member (the ObjectQL / engine contract, whereActionActivationlives) is this card's measurement;metadata-protocolimports nothing fromobjectql. - The plain sentence.
describeDisabled()rewritten for the person who clicked: no tracker number, no system table, no ADR citation (AGENTS.md's runtime-string rule, "the lesson goes into the text"); for example "This action is turned off for this deployment. An administrator can turn it on again under Setup › Packaged automation, or you can use another action." Both dispatch doors keep producing it from the one place; the existing refusal-sentence pins move with it. - Pins and an ablation. A switched-off action appears in the key and
item.actionsis byte-identical; no key when no ledger is attached; a cached read that carries the key is not answered 304 and the unjudged control still is; the list is keyed by object name; the sentence pins; one ablation on the serve path. - Consumer-package tests (a spec-lane card's standing commitment):
metadata-protocol,rest,objectql,runtime; the six regenerated spec artifacts; changeset (@objectstack/specminor,metadata-protocol/rest/objectqlpatch);Clause-②: yes (widening)⇒CONTRACT_REVIEW_TIERreview before queueing.
The exact key name (disabledActions is the triage route's literal spelling), and whether an empty array is served or the key omitted when the ledger holds no row for the object, are the seat's measurement and its contract review, not fixed here.
Dedupe
MCP search_issues on this repo, closed included: packaged action switched off activation state served with action metadata meta object disabledActions hide button → #27504 (the console half, parent of this split), #23316 (the flow twin, closed by PR #23358), #12348 (the activation write door, closed). None is this serve half.
Dedupe words: packaged action activation beside item; disabled actions envelope key meta object; action disabled refusal plain sentence.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 30, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 审批与自动化 | none | P②
Triage: p1 ·
domain:spec·area:automation· 2026-10-30T01:54Z⛔ Not a claim.
6512814276, letter B). It serves a new activation fact beside the item onGET /meta/object. A served key added to a published read is a protocol addition, and the standing rule is 「协议新增定 p1」. It isClause-②: yes: the maintainer approves the key in the PR, and a contract review is owed.actions[]and the stored item body stay as they are, per the card: novisible/disabledrewrite that would ride the GET → PUT round trip. The disabled-action sentence becomes a plain sentence for the end user, with the code and the ADR reference kept for the log.pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V
Claim: PM loop round 3 · 2026-10-30T03:37Z
Session:
session_017ihL2fi9zfJhUTubyJYb6VAccount:
marchtianBranch:
claude/issue-27842-disabled-actions-beside-itemWorktree:
objectstack-issue-27842Domain:
domain:specSeat:
domain:spec#4Ruling-ref: maintainer ruling 6512814276 on #27504 (letter B, the serve half to
domain:spec); triage 6513025554 ("It isClause-②: yes: the maintainer approves the key in the PR, and a contract review is owed." "⛔ The servedactions[]and the stored item body stay as they are … novisible/disabledrewrite." "The disabled-action sentence becomes a plain sentence for the end user, with the code and the ADR reference kept for the log.")File surface:
packages/spec/src/api/protocol.zod.ts(a key besideitemonGetMetaItemResponseSchema/GetMetaItemCachedResponseSchema, a name-keyed sibling ofitemson the list, after theregistration/registrationstemplate at L326, L682, L2318–2331 on88d60203), one optional read member on the engine-side contract inpackages/spec/src/contracts/**(thegetFlowRegistration?seam shape),packages/metadata-protocol/src/**(serve beside the item on both doors, never in the ETag),packages/objectql/src/action-activation.ts(describeDisabled()at L298 as a plain sentence; the projection the seam reads), the dispatch doors' refusal pins inpackages/rest/packages/runtimeas they move, tests in those four packages, regenerated spec artefacts, changesets (@objectstack/specminor;metadata-protocol/rest/objectqlpatch). ⛔ no change to servedactions[]or the stored item body (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: TIER_DEFAULT(opus) — the quota-exhaustion exemption (claude-fable-5-1answered HTTP 429; maintainer 「你没有fable了,使用 opus开发完之后等契约复审」),effort: highClause-②: yes (widening)
Metadata-protocol: added
Responsibility: the metadata reads every client builds action buttons from (
GET /api/v1/meta/object[/:name]) carry no activation fact, while dispatch refuses a switched-off packaged action 409ACTION_DISABLEDwith a sentence naming a system table and an ADR | the #23316registration-beside-the-item shape (PR #23358) is the path, as the action twin | every console, SDK and MCP consumer on a deployment where an administrator switched a packaged action off (measured onexamples/app-showcase, #27504)Thread-read: 6513025554
Premise: holds — on
88d60203protocol.zod.tscarriesregistrationbeside the item (L682, cached door L2326) andregistrationson the list (L326) and no activation key;describeDisabled()is atpackages/objectql/src/action-activation.ts:298; the seam templategetFlowRegistration?is atpackages/spec/src/contracts/automation-service.ts:1381Serial constraints cleared: draft PR #27713 (#27627) touches
packages/spec/src/api/index.tsand addsrecord-page.zod.ts, so the two PRs share the api barrel and the generated api-surface; whichever lands second mergesorigin/mainand regenerates (scripts/pm/os-regen-merge.sh). No open PR touchesprotocol.zod.ts,action-activation.tsor the metadata-protocol serve path (open PR file lists read just before this claim)objectstack-fleet commentedon Oct 30, 2026
domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V
os-dev-report
{ "issue": 27842, "status": "done", "branch": "claude/issue-27842-disabled-actions-beside-item", "pr": "https://github.com/objectstack-ai/objectstack/pull/27964", "head": "7237921e365096628921e03d89f7bc18d3cb9d85", "session": "session_017ihL2fi9zfJhUTubyJYb6V", "premise_still_valid": true, "summary": "GET /meta/object/:name (protocol door and the cached default REST door) and GET /meta/object serve `disabledActions` beside the item: string[] on the item reads, Record<objectName,string[]> on the list. It is read through the `objectql` service slot for the new optional IObjectQLEngine.getDisabledActions (metadata-protocol imports no objectql). The key is absent when no ledger answered and [] when a ledger answered with nothing off, following `registration`. It is never in the ETag, and a read that carries it is never 304. item.actions is untouched. The ACTION_DISABLED 409 now carries a plain end-user sentence; the code, table and ADR-0126 §8 move to an info log line written in ObjectQL.describeDisabledAction. Key name `disabledActions` awaits the maintainer's approval in the PR (Clause-② yes).", "key_name": "disabledActions", "empty_vs_absent": "absent = no ledger answered (no objectql service, engine without getDisabledActions, or getDisabledActions() === undefined because no store is attached); [] = a ledger answered and none of this object's actions is off. Measured on `registration`: every served flow gets a verdict once the engine answers, and the list has one entry per listed non-draft item; absence is reserved for 'no engine declares the member'.", "tests": "Full suites on the final head, exit codes recorded: spec typecheck 0 / test 0 (756 files, 22483 passed); metadata-protocol 0 / 0 (21854 passed); objectql 0 / 0 (493 files, 9587 passed); rest 0 / 0 (350 files, 6759 passed); runtime test 0 (481 files, 7837 passed), runtime typecheck 1 then 0 (first run TS2307 in organization-ownership-boot-guard.turso-remote.kernel.test.ts, not in the diff: no local driver-turso dist; rerun 0 after building it). Ablation: the item-read spread in metadata-protocol/src/protocol.ts was replaced via ablation-replace and src/protocol.object-disabled-actions.test.ts gave 5 failed / 6 passed (item read and cached cases red, absence controls and list green); restore proven (blob == HEAD, git diff HEAD empty).", "gates": "dispatch-gates --commands on the final head 7237921e36: 119 commands, each exit code recorded before any pipe. --ran: '119 derived, 119 run, 0 NOT-MEASURED, 0 UNRUN' (exit 0). First pass: check:skill-examples exit 3 and check:dual-build-cjs-loads exit 3 (PREREQUISITE: missing dist) became 0 after a full package build. check:engine-double-contract exit 1 (RETAINED: the new test's pinned findOne double was not in the ledger) became 0 after --write, which added that single entry, committed as 7237921e36. That commit derived 8 more scripts gates, all exit 0. CI check-runs on 7237921e36 at report time: 9 success, 7 skipped, 18 in progress, 0 failed (not final).", "line_budget": "no budget set by the order; diff +1127/-45 across 23 files (dispatch-gates: 1167 changed lines vs the human-merge threshold 3000: under)", "files_changed": [ ".changeset/27842-disabled-actions-beside-item.md +10/-0", ".changeset/27842-disabled-actions-served.md +15/-0", "content/docs/references/api/protocol.mdx +3/-0", "docs/qa/platform-checklist/areas/api-backend.json +9/-3", "packages/metadata-protocol/src/protocol-action-activation-reads.ts +102/-0", "packages/metadata-protocol/src/protocol.object-disabled-actions.test.ts +244/-0", "packages/metadata-protocol/src/protocol.ts +66/-2", "packages/objectql/src/action-activation.test.ts +52/-5", "packages/objectql/src/action-activation.ts +20/-8", "packages/objectql/src/engine.ts +26/-1", "packages/objectql/src/protocol-meta-disabled-actions.test.ts +217/-0", "packages/qa/dogfood/test/packaged-action-disabled-dispatch-live.dogfood.test.ts +15/-5", "packages/qa/dogfood/test/packaged-activation-ledger-reach.dogfood.test.ts +3/-1", "packages/rest/src/meta-item-read-routes.ts +18/-3", "packages/rest/src/meta-object-cached-disabled-actions.test.ts +131/-0", "packages/runtime/src/action-execution.ts +4/-2", "packages/runtime/src/domains/action-activation-dispatch.test.ts +30/-12", "packages/runtime/src/domains/api-action-forward.test.ts +3/-3", "packages/spec/authorable-surface/api.json +3/-0", "packages/spec/src/api/meta-item-response-shapes.test.ts +59/-0", "packages/spec/src/api/protocol.zod.ts +68/-0", "packages/spec/src/contracts/objectql-engine.ts +24/-0", "scripts/engine-double-contract.pinned.json +5/-0" ], "deviations": [ "The log line (ACTION_DISABLED, action name, sys_metadata_activation, ADR-0126 §8 item 2) is written by ObjectQL.describeDisabledAction rather than by the dispatch domains: HttpDispatcher's deps.logger is not wired, and that method is the one call both doors make on every refusal.", "No Fable or other independent review was run, per the order's exception; the PR waits for the seat's contract-review hand-off.", "The PR body ends with the order's footer lines and carries no separate '_Generated by …/session_…_' line.", "The two dogfood test files edited for the pin sweep were not run locally (they boot example apps; CI's Dogfood gate runs on main after the merge).", "scripts/engine-double-contract.pinned.json is in the diff: one ledger entry the gate requires for the new test's findOne double." ], "pins_flipped": [ "packages/objectql/src/action-activation.test.ts — the sentence pin (exact plain text, no table/ADR) and the engine pin (equals the projection)", "packages/runtime/src/domains/action-activation-dispatch.test.ts — the double now calls ActionActivationProjection.describeDisabled; REST 409 sentence test; MCP door sentence assertion; new fallback test", "packages/runtime/src/domains/api-action-forward.test.ts — the double now calls the projection", "packages/qa/dogfood/test/packaged-action-disabled-dispatch-live.dogfood.test.ts — expectDisabledSentence helper", "packages/qa/dogfood/test/packaged-activation-ledger-reach.dogfood.test.ts — /ACTION_DISABLED|is disabled/ became the code", "docs/qa/platform-checklist/areas/api-backend.json — api-backend.packaged-action-disabled-dispatch acceptance[0], revision 9→10 with a history entry" ], "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (fleet-write dispatch run 41008560946 → POST /repos/objectstack-ai/objectstack/pulls, #27964, draft, no assignees/reviewers/labels), and this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/27842/comments via post-stamped). git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "carrier: seat (domain:spec#4) · noted, not filed · class: none (doc drift, observation) · evidence: docs/qa/platform-checklist/areas/platform-core.json ledger posture note says 'the data-API read IS the only \"what is off here\" surface today'; after #27964 GET /meta/object also answers it · dedupe: platform-core checklist, what is off here, activation ledger surface", "carrier: seat (domain:spec#4) · noted, not filed · class: a candidate (misleading end-user copy) · reach: NOT measured, read-only inference · evidence: packages/services/service-automation/src/subflow-guards.ts:50 describeDisabledFlow names sys_metadata_activation and ADR-0126 §7.2 in the FLOW_DISABLED refusal; the automation checklist (negative[3]) deliberately keys on that message · dedupe: FLOW_DISABLED, describeDisabledFlow, plain sentence, flow ledger refusal", "carrier: seat contract review on #27964 · noted, not filed · class: none (design trade the card fixes) · evidence: with a ledger attached (every PlatformObjectsPlugin boot), every cached GET /meta/object/:name answers 200, not 304; alternative: fold the switched-off names into the REST validator fingerprint as visibility, runtime-view and audience are folded · dedupe: disabledActions 304, meta object etag, cached door revalidation", "carrier: none · noted, not filed · class: none (observation) · evidence: HttpDispatcher domain deps logger appears unwired ((this as any).logger), so domain log lines fall back to console · dedupe: HttpDispatcher logger, deps.logger" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V
Landed · 2026-10-30T10:55Z · PR #27964 merged by the queue at 2026-10-30T10:54Z as
3e0fd7a8f7; the card closed byFixes. This seat stripspm:dispatchedin the same act. Before landing, the maintainer approved the key name and the 304 cost (PR comment 6520565524). The follow-ups are filed: #28044 brings 304s back on object reads by folding the switched-off names into the ETag, and #27966 gives the flow twin'sFLOW_DISABLEDsentence the same plain shape. The console still has to readdisabledActionsbefore buttons hide; that is the UI consumer's work, not this card's.