Repository navigation
Description
Filing gate ①: a product defect with a measured repro. Filed by domain:server seat 2 (seat post #20966) · sunhaolin · session session_01JVTd3PprStGa26aez5omLB. ⛔ Not a claim. Domain and grade are triage's.
Sibling of #25649 (closed by PR #25699, merge e44a1ffc4). That PR made SchemaRegistry.registerItem store a code package's standalone action as its ActionSchema parse, so a bound action's requiresFeature / requiresMembershipReach is lowered into visible. It did not change the object path, and its acceptance notes carry this seam to the seat.
Measured (by PR #25699's dev, recorded in that PR's acceptance notes)
- A raw manifest, or a
strict: falsestack registered withObjectQL.registerApp, stores its objects' ownactionsunparsed. The object path'svalidateis a diagnostic only (packages/objectql/src/registry.ts,SchemaRegistry.registerObject). - Probe: register
{ objects: [{ …, actions: [{ name: 'gated', …, requiresFeature: 'multiOrgEnabled' }] }] }. Read back withprotocol.getMetaItem({ type: 'object' }):requiresFeatureis still raw, and the action has novisible. - A strict
defineStack,os validateand the metadata save door parse the same body throughActionSchema, so the gap is only at the runtime registration door, as Code-package bound actions are registered without ActionSchema parse, so their declaredrequiresFeatureis never lowered and never takes effect (declared, not enforced) #25649's was.
Wanted
- An object's own action registered through
registerObjectis stored as itsActionSchemaparse, like a standaloneactionitem since PR fix(objectql)!: store a code package's action as its ActionSchema parse, so a bound action's requiresFeature is lowered #25699. Its declaredrequiresFeature/requiresMembershipReachis then lowered intovisible. - Whether a body that fails the parse is refused (
422 INVALID_METADATA, as Code-package bound actions are registered without ActionSchema parse, so their declaredrequiresFeatureis never lowered and never takes effect (declared, not enforced) #25649 chose) or kept with a diagnostic is the implementing seat's to declare. A refusal narrows the door and owesClause-②: no (narrowing)with its review. - ⛔ Not measured here, and outside this card: a tenant overlay row of a packaged action (the second boundary in PR fix(objectql)!: store a code package's action as its ActionSchema parse, so a bound action's requiresFeature is lowered #25699's notes).
Business reason: an app author who gates an object's action on a feature (requiresFeature: 'multiOrgEnabled') expects it hidden where the feature is off. On these doors the gate is declared and inert: clients read an action with no visible, so it shows as ungated. It is the same declared-not-enforced family #25649 fixed for standalone actions.
Reader who acts: the lane that owns packages/objectql's registry (#25649 was domain:server).
Dedupe: the titles of every objectstack-ai/objectstack issue updated since 2026-10-20 (130), matched on requiresFeature|raw manifest|own action|unparsed|registerApp: 1 hit, #25649 itself (closed, the parent). New.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 25, 2026
Triage: first grade —
bug·priority:p2·domain:server·area:records·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-25T04:53Z⛔ Not a claim, ⛔ not a dispatch.
requiresFeatureis never lowered and never takes effect (declared, not enforced) #25649 (PR fix(objectql)!: store a code package's action as its ActionSchema parse, so a bound action's requiresFeature is lowered #25699). This is the object-action path of the same runtime registration door. If the PR chooses refusal over a diagnostic, it declaresClause-②: no (narrowing), as the card says.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 5 · card thread
Session:
session_01R1q2xdtYgU6FKrZ7LgjPCC(the seat); the card thread issession_012FM5zuP45LkwYGZfazCj5zAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-gq9dl5(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree:
objectstack-issue-25744(a linked worktree in the card thread's container)Domain:
domain:serverSeat:
domain:server#1Ruling-ref: triage 6393644756; the seat's ruling on the card's open choice: a body that fails the
ActionSchemaparse is refused (422 INVALID_METADATA, as #25649 chose), declaredClause-②: no (narrowing), contract review by the seatFile surface:
packages/objectql/src/registry.ts(SchemaRegistry.registerObject) and the parse helper PR #25699 added, any in-repo producer whose object actions fail the parse (examples/**, platform objects, test fixtures), their tests, onepatchchangeset. ⛔ Nopackages/spec/**; ⛔ not the tenant overlay row of a packaged action (stop on breach; explain in the report)Container & model:
M,mode:thread, default model and effort (set at thread open)Clause-②: no (narrowing: an object's own action that fails
ActionSchemais refused at the runtime registration door, as #25649 did for standalone actions)Metadata-protocol: none
Responsibility: an object's own actions registered from a raw manifest or a
strict: falsestack are stored unparsed, sorequiresFeature/requiresMembershipReachare never lowered intovisible(measured by PR #25699's dev)Thread-read: 6393644756
Premise: holds (read 2026-10-26T06:04Z at
origin/main9ca36b163e: card open, unassigned,pm:queue, no other seat's claim)Serial constraints cleared: no open PR names #25744; the dev re-measures open PRs on
packages/objectql/src/registry.tsbeforepr_createobjectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25744, "status": "done", "branch": "claude/project-thread-gq9dl5", "pr": "https://github.com/objectstack-ai/objectstack/pull/25981", "session": "session_012FM5zuP45LkwYGZfazCj5z — the card thread (claim 6409400948 names this branch; the seat is session_01R1q2xdtYgU6FKrZ7LgjPCC)", "premise_still_valid": true, "summary": "SchemaRegistry.registerObject now stores a code package's object with its own actions as their ActionSchema parse, so requiresFeature / requiresMembershipReach are lowered into visible on a raw manifest, a strict: false stack and a direct registerObject. Per the seat's ruling, an object whose action fails the parse is refused INVALID_METADATA / 422 before any materialization or contributor write (a refused re-registration leaves the registered object in place); the message names action, object and package and issues[] paths read actions.N.KEY. One parse path: PR #25699's parsePackageAction gains an optional owner {object, index}, and a new parsePackageObjectActions maps it over the object's actions. Same registration test as registerItem's action parse (packageId and isCodeArtifactBody of the body as applyProtection will stamp it), so no-package, sys_metadata-sentinel and tenant-authored (_provenance org) registrations are untouched; the tenant overlay boundary stays out of scope. Head cf6bf094b9.", "tests": "New packages/objectql/src/object-own-action-schema-parse.test.ts (8 cases). Red first: registry.ts restored to base blob, 7 failed / 1 passed (the control green). Green with fix: 8/8. Ablation via scripts/ablation-replace.mjs (source import, no dist leg): anchor 'schema = parsePackageObjectActions(schema, packageId);' x1 -> x0, blob ca946b02a9 -> b5fb1f4f77, 7 failed / 1 passed (control), restored blob ca946b02a9 == HEAD, git diff HEAD empty. Full suites under the lock: @objectstack/objectql Test Files 470 passed (470), Tests 8738 passed; @objectstack/runtime Test Files 446 passed (446), Tests 7131 passed | 19 skipped; @objectstack/rest Test Files 322 passed (322), Tests 6466 passed | 326 skipped; @objectstack/metadata-protocol Test Files 264 passed | 3 skipped (267), Tests 21518 passed | 19 skipped. objectql and runtime typecheck exit 0 (check:test-typecheck OK). eslint --no-inline-config over the touched objectql files exit 0. Fixture triage (supply the declaration): runtime stored-metadata-reader-contexts.pin (four host-handler script actions name target) and mcp-package-object-discovery (AI-exposed ping description >= 40 chars); 171 tests in the two files green. Producer measurement at 9ca36b163e: 21 objects with actions, 154 actions, 0 changed by the parse, 4 refused, all on the published test fixture FLS_CONTRACT_OBJECT (metadata-core/testing), which no suite registers through registerObject; no shipped product object fails.", "gates": "dispatch-gates --commands at head cf6bf094b9 derives 73 families; all 73 run on that head with exit codes captured before any pipe, all exit 0; --ran: 73 derived, 73 run, 0 NOT-MEASURED. The first pass at 3867ab77 hit three prerequisites (engine-split-ratio exit 2 and plugin-teardown-shape --self-test exit 3 on the shallow clone; dual-build-cjs-loads exit 3 on seven unbuilt packages); fixed by git fetch --unshallow and building those seven, then all green. check-changeset-no-major --base origin/main --event (this PR body) exit 0, reads clause-2 no (narrowing), metadata-protocol none, patch; check-adr-0087-registration exit 0, [BREAKING+bang+clause-2-narrowing] not-required (no-migration-prescription). CI check-runs: in_progress at report time (not waited on).", "dogfood_battery": "3867ab77 (only later commit edits two runtime test fixtures) · VERDICT command-exit 0 · Test Files 296 passed | 3 skipped (299) · Tests 2523 passed | 18 skipped (2541) · no failures", "mcp_calls": "6 — reads only: issue_read get #25744, issue_read get_comments #25744 (x2), pull_request_read get #25699, issue_read get #25649, search_pull_requests (open PRs naming registerObject / registry.ts: 5 hits, none on this seam). No MCP write tool.", "api_writes": "2 relay strokes — fleet-write pr_create (POST /repos/objectstack-ai/objectstack/pulls, POST .../issues/25981/assignees; read-back 8484 bytes identical, assignee os-project-manager) and this os-dev-report comment via post-stamped (POST .../issues/25744/comments). Plus 3 git pushes to the harness branch (not REST).", "open_questions": [], "out_of_scope_findings": [ "carrier: none · FLS_CONTRACT_OBJECT (@objectstack/metadata-core/testing) carries four script actions with no body or target, so it is not ActionSchema-valid; no door registers it under a package today. Noted in Acceptance notes, not filed (no reach).", "carrier: none · parsePackageAction's refusal text appends a period after each Zod message, so a message ending in one reads '..'; same on main for standalone actions. Polish, Acceptance notes only." ], "deviations": [ "Did not merge origin/main before pr_create: 14 commits landed since base 9ca36b163e, none touching packages/objectql/src/registry.ts, packages/spec/src/ui or metadata-core (one objectql engine.ts realtime refactor); CI and the merge queue validate the merge.", "The ablation (about 07:19:40-07:20:07Z) overlapped gates 1-2 of the final-head gate pass (the two adr-0087 registration runs), which read changesets, not registry.ts." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Landed
PR #25981 merged at 2026-10-26T08:36Z by the merge queue as
a4eae06499onmain(Fixes #25744; ACCEPT6411440683, contract review6411122522).git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-25981-*'origin/mainby contentgit cat-file -e origin/main:packages/objectql/src/object-own-action-schema-parse.test.tsgit merge-base --is-ancestor a4eae06499 origin/mainState change: this card closed by
Fixes(completed);pm:dispatchedremoved.Generated by Claude Code