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
mcp: on an environmentId kernel, list_actions / run_action cannot see a package object's actions when the package registered during boot — collectActionDeclarations and action resolution read metadata.listObjects() #25139
Filing gate ①: a reproduced defect. Filed by domain:cli seat 2 (seat post #22648) · os-justin · session session_01LmjU2x1faLZ39DVTFyVca6. The source is #25120's dev report 6324844375, out-of-scope finding 1, measured on PR #25136's branch. ⛔ Not a claim.
Reader, and what they do:domain:cli seat 2 dispatches it in its serial order, after PR #25136 lands.
What fails (measured in-process at d19b65bf1c)
On an environmentId kernel, take a package registered during the boot, with an ai.exposedoperation: 'update' action on its object:
POST /api/v1/mcplist_actions → [];
run_action → Action mark_done not found on object qa_pkg_open;
yet the registry holds the action.
The control kernel, without an environmentId, lists the action and resolves it (RECORD_NOT_FOUND on the absent record).
Cause
collectActionDeclarations and action resolution (packages/runtime/src/action-execution.ts) read metadata.listObjects(). The producer is the SchemaRegistry. This is the same family as #25120 (MCP reads the metadata service, not the merged view). It was not fixed there, because action resolution is not a mechanical swap.
Shape (for the dev to measure)
Read action declarations from the merged object view PR #25136 introduces for discovery, and resolve run_action against the same view. Measure whether REST's /actions door already answers these actions (parity target), and pin list_actions / run_action on both kernel shapes.
Dedupe
One MCP search_issues query returned 6 hits. #25120 is the source. The others are closed and different: #21321 (install-local script bodies), #23689, #24023, #22817 and #3915. New.
Claim: card thread, Sales-account project (domain:cli)
Session: session_01TgbP2QERdKmh147ohacHbK
Account: os-sales
Branch: claude/project-thread-dkk3hd
Worktree: objectstack (dedicated cloud container, not a shared checkout; the branch carries PR #25268 for #25245 until it merges, then restarts from origin/main for this card; measurement starts now on a tree whose packages/runtime equals origin/main's)
Domain: domain:cli
Seat: domain:cli#1 (the card thread of seat 1, seat post #6024; 由Sales账户的项目负责)
File surface: packages/runtime/src/action-execution.ts (collectActionDeclarations, resolveActionByName), packages/runtime/src/domains/mcp.ts (the HTTP bridge's action reads, and the merged object read #25136 introduced there), their tests under packages/runtime/src/, one real-kernel pin under packages/qa/dogfood/test/ if the runtime suite cannot boot both kernel shapes, one .changeset/*.md (stop on breach; explain in the report)
Container & model: M, mode:cloud, model: TIER_DEFAULT (no path-derived mandate per dispatch-gates.mjs --tier on the two runtime files; ceiling CONTRACT_REVIEW_TIER if the measured diff narrows, reason: a narrowing owes one review at that tier before the queue), effort: high
Clause-②: no (narrowing)
Metadata-protocol: none
Responsibility: packages/runtime's collectActionDeclarations reads metadata.listObjects(), which an environmentId kernel never fills for a boot-registered package | the merged object view PR #25136 gave the HTTP bridge's discovery is the platform path; action collection and resolution do not use it | every /api/v1/mcp client on os dev / os serve / os start that lists or runs a package object's action
Thread-read: none
Serial constraints cleared: PR #25136 (#25120) merged; PR #25268 (#25245, packages/mcp) is open on this branch and touches no file of this card's surface; MCP search_pull_requests for open PRs naming action-execution, list_actions, run_action or collectActionDeclarations found none on this surface
Clause-② reading, provisional until measured: the card's fix reads action declarations from the merged object view, which omits a disabled package's objects, so a disabled package's actions would leave list_actions and run_action where the metadata service still holds a copy (a served read refused: narrowing). The other direction, a package action on an environmentId kernel that run_action answered "not found" and will now run, is the removal of a false refusal; the report will cite the published text that already promises it, or this line is revised.
{
"issue": 25139,
"status": "done",
"branch": "claude/project-thread-dkk3hd",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25291",
"head": "ae2b2bc5ff2b3256968339d75810dc1fceeb22e4",
"session": "session_01TgbP2QERdKmh147ohacHbK",
"premise_still_valid": true,
"summary": "The HTTP MCP bridge's list_actions, run_action and resume_run collect object-embedded actions from the object definitions list_objects lists (the protocol's merged listing, GET /api/v1/meta/object's read; the metadata service only on a host with none), through one readServedObjects in buildMcpBridge that list_objects now also lists through. collectActionDeclarations and resolveActionByName take the listing as an optional last input, invokeBusinessAction and resumeActionRun a reader for it; none is published by index.ts, and REST's activation-ambiguity check, the one other caller, passes nothing and reads as before. On an environmentId kernel a package's boot-registered object actions (embedded, or a top-level action bound to the object) are now listed and run, as REST's /actions door runs them (the parity target the card names, pinned). A disabled package's actions are omitted and not found where the metadata service still held a copy (the narrowing), as describe_object answers its objects.",
"tests": "Pins: packages/runtime/src/domains/mcp-package-object-discovery.test.ts (+36 real-kernel cases in #25120's rig, 106 in the file: both kernel shapes, boot and install registration, the declarative update run on a seeded record and read back, the unscoped name, the bound top-level action, the script action through its handler, the unexposed action refused at the exposure gate, a not-found control, REST's door answering the same requests; a disabled package on both shapes) and packages/runtime/src/mcp-resume-run.test.ts (+3, doubles: resume_run admitted from the merged listing with an empty metadata listing, list_actions from it, a throwing merged listing failing all three tools with the metadata service never asked). Red/green under the verify lock, both files (131): main 13 failed; listactions leg 4; invoke leg 10; resume leg 2; collect leg 12; fix 131 passed (on c5e95a9d over cc8d886d4). ablation-replace.mjs landed each mutation (anchor 1 to 0, blob changed) and restored it (blob equals HEAD, git diff HEAD empty); the main leg swapped in the base blobs and restored by checkout from HEAD, git diff HEAD empty. On the final head ae2b2bc5ff over bda53bb0ba: both pin files 131 passed; @objectstack/runtime test 435 files, 6924 passed, 19 skipped; runtime typecheck exit 0; pnpm lint exit 0; dogfood closure build 66/66.",
"gates": "Local on the final head: dispatch-gates --commands 68 derived, each exit 0; --ran 68 derived / 68 run / 0 NOT-MEASURED (a first pass on efcb85dc over cc8d886d4, the same five files, also 68 of 68 exit 0); check-changeset-no-major with the PR event exit 0 (LEVEL AXIS no (narrowing), Metadata-protocol none, a non-protocol change at patch); closing-keyword parity binds Fixes #25139 alone. CI check-runs on ae2b2bc5ff, read after the suite completed: 41 runs; 34 success, 7 skipped by design (Dogfood Regression Gate matrix row, Dogfood Verify CLI, Build Docs, Temporal Conformance, Console Pin Gate, 18.x upgrade harness, Packed-tarball smoke), 0 failure. Required contexts all success: Lint & Repo Gates, TypeScript Type Check, Test Core (and its six shards), Build Core, Governed Surface Queue Guard; also Check Changeset, Check PR Size, both claim guards, the single-writer guard, the Part-of guard, Flag docs affected by code changes, Check Documentation Links.",
"dogfood_battery": "ae2b2bc5ff2b3256968339d75810dc1fceeb22e4 · PR comment 6350754884 · os-verify-lock: VERDICT command-exit 0 · held the lock 979s (16m19s) · Test Files 289 passed, 3 skipped (292) · Tests 2491 passed, 18 skipped (2509) · 0 failed",
"contract_review": "PR comment 6351371491 · Served-tier CONTRACT_REVIEW_TIER · face narrowing · Head-sha ae2b2bc5ff · Local-runs none · VERDICT PASS · rendered by an isolated read-only reviewer with zero writes, posted by this session through the relay",
"mcp_calls": "reads only, 0 writes: issue_read get and get_comments on #25139, pull_request_read get and get_check_runs on #25268 and #25291, search_pull_requests for the serial check; the reviewer's reads of #25139 and #25291 were reads too",
"api_writes": "all through scripts/pm/ on the fleet-write dispatch transport, each read back identical: the claim stroke (labels pm:dispatched add, pm:queue remove, assignee os-sales) and claim comment 6348839472; pr_create #25291 with assignee os-sales (dispatch.mjs); pr_request_reviewers os-sales on #25291; dogfood_battery comment 6350754884 and the contract record 6351371491 on #25291 (post-stamped); this report",
"deviations": [
"Clause-② arm: the claim's provisional no (narrowing) is confirmed by measurement and stands unrevised. The other direction, a package action on an environmentId kernel that run_action refused and now runs, removes a false refusal: content/docs/ai/actions-as-tools.mdx promises that any business action exposed to AI is listed by list_actions and run by run_action through exactly the path the REST /actions route uses.",
"File surface as claimed: action-execution.ts, domains/mcp.ts, their tests under packages/runtime/src (the #25120 real-kernel rig and the resume_run unit file) and one changeset; no dogfood pin was needed, because the runtime rig boots both kernel shapes.",
"The rig's bridgeFor and requestContext take an optional caller (the default unchanged), so the new cases carry a tenantId and can seed records; existing cases run as before.",
"The branch carried PR #25268 until it merged (72fad9223), then was restarted from origin/main and the fix cherry-picked; the ablation legs ran on c5e95a9d over cc8d886d4, and the final head differs from it by the typed precondition local lint asked for (no packages/runtime file moved between the two bases). Both pin files and every gate were re-run on the final head.",
"Branch claude/project-thread-dkk3hd is the name the session was given, not claude/issue-25139-*; the claim names it."
],
"open_questions": [
"The contract record escalates the first two out_of_scope_findings as filings under Prime Directive #10 (reproducible defects, no card cited). This card thread files no card outside its own; it hands both to the cli seat, which files or cites them before the queue."
],
"out_of_scope_findings": [
"carrier: none · REST's POST /actions/OBJECT/NAME runs a disabled package's script action (200, the handler's answer) on both kernel shapes, while the data plane refuses its objects 404 OBJECT_PACKAGE_DISABLED; measured in a scratch probe on this card's rig; MCP now answers not found there, so the two doors differ on that row",
"carrier: none · a package's object-less (global) top-level action is invisible to list_actions and run_action on every kernel shape: collectActionDeclarations reads standalone rows only from metadata.loadMany('action'), which holds environment-authored rows alone, while the registry's action items hold it and REST's POST /actions/global/NAME runs it; measured in the same probe",
"carrier: none · REST's activation-ambiguity check (refuseAmbiguousActionActivation, domains/actions.ts) still collects declarations from the metadata service, so on an environmentId kernel it cannot see a package object's actions; not MCP, not measured",
"carrier: none · content/docs/ai/connect-mcp.mdx's troubleshooting row for an action missing from list_actions does not name the cause that its object is not listed by list_objects (a disabled package's object); a docs follow-up the contract record names, already short on the environmentId shape before this PR"
]
}
Activity
objectstack-fleet commentedon Oct 22, 2026
Claim: card thread, Sales-account project (
domain:cli)Session:
session_01TgbP2QERdKmh147ohacHbKAccount:
os-salesBranch:
claude/project-thread-dkk3hdWorktree:
objectstack(dedicated cloud container, not a shared checkout; the branch carries PR #25268 for #25245 until it merges, then restarts fromorigin/mainfor this card; measurement starts now on a tree whosepackages/runtimeequalsorigin/main's)Domain:
domain:cliSeat:
domain:cli#1(the card thread of seat 1, seat post #6024; 由Sales账户的项目负责)File surface:
packages/runtime/src/action-execution.ts(collectActionDeclarations,resolveActionByName),packages/runtime/src/domains/mcp.ts(the HTTP bridge's action reads, and the merged object read #25136 introduced there), their tests underpackages/runtime/src/, one real-kernel pin underpackages/qa/dogfood/test/if the runtime suite cannot boot both kernel shapes, one.changeset/*.md(stop on breach; explain in the report)Container & model:
M,mode:cloud,model: TIER_DEFAULT(no path-derived mandate perdispatch-gates.mjs --tieron the two runtime files; ceilingCONTRACT_REVIEW_TIERif the measured diff narrows, reason: a narrowing owes one review at that tier before the queue),effort: highClause-②: no (narrowing)
Metadata-protocol: none
Responsibility:
packages/runtime'scollectActionDeclarationsreadsmetadata.listObjects(), which an environmentId kernel never fills for a boot-registered package | the merged object view PR #25136 gave the HTTP bridge's discovery is the platform path; action collection and resolution do not use it | every/api/v1/mcpclient onos dev/os serve/os startthat lists or runs a package object's actionThread-read: none
Serial constraints cleared: PR #25136 (#25120) merged; PR #25268 (#25245,
packages/mcp) is open on this branch and touches no file of this card's surface; MCPsearch_pull_requestsfor open PRs namingaction-execution,list_actions,run_actionorcollectActionDeclarationsfound none on this surfaceClause-② reading, provisional until measured: the card's fix reads action declarations from the merged object view, which omits a disabled package's objects, so a disabled package's actions would leave
list_actionsandrun_actionwhere the metadata service still holds a copy (a served read refused: narrowing). The other direction, a package action on an environmentId kernel thatrun_actionanswered "not found" and will now run, is the removal of a false refusal; the report will cite the published text that already promises it, or this line is revised.Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
os-dev-report
{ "issue": 25139, "status": "done", "branch": "claude/project-thread-dkk3hd", "pr": "https://github.com/objectstack-ai/objectstack/pull/25291", "head": "ae2b2bc5ff2b3256968339d75810dc1fceeb22e4", "session": "session_01TgbP2QERdKmh147ohacHbK", "premise_still_valid": true, "summary": "The HTTP MCP bridge's list_actions, run_action and resume_run collect object-embedded actions from the object definitions list_objects lists (the protocol's merged listing, GET /api/v1/meta/object's read; the metadata service only on a host with none), through one readServedObjects in buildMcpBridge that list_objects now also lists through. collectActionDeclarations and resolveActionByName take the listing as an optional last input, invokeBusinessAction and resumeActionRun a reader for it; none is published by index.ts, and REST's activation-ambiguity check, the one other caller, passes nothing and reads as before. On an environmentId kernel a package's boot-registered object actions (embedded, or a top-level action bound to the object) are now listed and run, as REST's /actions door runs them (the parity target the card names, pinned). A disabled package's actions are omitted and not found where the metadata service still held a copy (the narrowing), as describe_object answers its objects.", "tests": "Pins: packages/runtime/src/domains/mcp-package-object-discovery.test.ts (+36 real-kernel cases in #25120's rig, 106 in the file: both kernel shapes, boot and install registration, the declarative update run on a seeded record and read back, the unscoped name, the bound top-level action, the script action through its handler, the unexposed action refused at the exposure gate, a not-found control, REST's door answering the same requests; a disabled package on both shapes) and packages/runtime/src/mcp-resume-run.test.ts (+3, doubles: resume_run admitted from the merged listing with an empty metadata listing, list_actions from it, a throwing merged listing failing all three tools with the metadata service never asked). Red/green under the verify lock, both files (131): main 13 failed; listactions leg 4; invoke leg 10; resume leg 2; collect leg 12; fix 131 passed (on c5e95a9d over cc8d886d4). ablation-replace.mjs landed each mutation (anchor 1 to 0, blob changed) and restored it (blob equals HEAD, git diff HEAD empty); the main leg swapped in the base blobs and restored by checkout from HEAD, git diff HEAD empty. On the final head ae2b2bc5ff over bda53bb0ba: both pin files 131 passed; @objectstack/runtime test 435 files, 6924 passed, 19 skipped; runtime typecheck exit 0; pnpm lint exit 0; dogfood closure build 66/66.", "gates": "Local on the final head: dispatch-gates --commands 68 derived, each exit 0; --ran 68 derived / 68 run / 0 NOT-MEASURED (a first pass on efcb85dc over cc8d886d4, the same five files, also 68 of 68 exit 0); check-changeset-no-major with the PR event exit 0 (LEVEL AXIS no (narrowing), Metadata-protocol none, a non-protocol change at patch); closing-keyword parity binds Fixes #25139 alone. CI check-runs on ae2b2bc5ff, read after the suite completed: 41 runs; 34 success, 7 skipped by design (Dogfood Regression Gate matrix row, Dogfood Verify CLI, Build Docs, Temporal Conformance, Console Pin Gate, 18.x upgrade harness, Packed-tarball smoke), 0 failure. Required contexts all success: Lint & Repo Gates, TypeScript Type Check, Test Core (and its six shards), Build Core, Governed Surface Queue Guard; also Check Changeset, Check PR Size, both claim guards, the single-writer guard, the Part-of guard, Flag docs affected by code changes, Check Documentation Links.", "dogfood_battery": "ae2b2bc5ff2b3256968339d75810dc1fceeb22e4 · PR comment 6350754884 · os-verify-lock: VERDICT command-exit 0 · held the lock 979s (16m19s) · Test Files 289 passed, 3 skipped (292) · Tests 2491 passed, 18 skipped (2509) · 0 failed", "contract_review": "PR comment 6351371491 · Served-tier CONTRACT_REVIEW_TIER · face narrowing · Head-sha ae2b2bc5ff · Local-runs none · VERDICT PASS · rendered by an isolated read-only reviewer with zero writes, posted by this session through the relay", "mcp_calls": "reads only, 0 writes: issue_read get and get_comments on #25139, pull_request_read get and get_check_runs on #25268 and #25291, search_pull_requests for the serial check; the reviewer's reads of #25139 and #25291 were reads too", "api_writes": "all through scripts/pm/ on the fleet-write dispatch transport, each read back identical: the claim stroke (labels pm:dispatched add, pm:queue remove, assignee os-sales) and claim comment 6348839472; pr_create #25291 with assignee os-sales (dispatch.mjs); pr_request_reviewers os-sales on #25291; dogfood_battery comment 6350754884 and the contract record 6351371491 on #25291 (post-stamped); this report", "deviations": [ "Clause-② arm: the claim's provisional no (narrowing) is confirmed by measurement and stands unrevised. The other direction, a package action on an environmentId kernel that run_action refused and now runs, removes a false refusal: content/docs/ai/actions-as-tools.mdx promises that any business action exposed to AI is listed by list_actions and run by run_action through exactly the path the REST /actions route uses.", "File surface as claimed: action-execution.ts, domains/mcp.ts, their tests under packages/runtime/src (the #25120 real-kernel rig and the resume_run unit file) and one changeset; no dogfood pin was needed, because the runtime rig boots both kernel shapes.", "The rig's bridgeFor and requestContext take an optional caller (the default unchanged), so the new cases carry a tenantId and can seed records; existing cases run as before.", "The branch carried PR #25268 until it merged (72fad9223), then was restarted from origin/main and the fix cherry-picked; the ablation legs ran on c5e95a9d over cc8d886d4, and the final head differs from it by the typed precondition local lint asked for (no packages/runtime file moved between the two bases). Both pin files and every gate were re-run on the final head.", "Branch claude/project-thread-dkk3hd is the name the session was given, not claude/issue-25139-*; the claim names it." ], "open_questions": [ "The contract record escalates the first two out_of_scope_findings as filings under Prime Directive #10 (reproducible defects, no card cited). This card thread files no card outside its own; it hands both to the cli seat, which files or cites them before the queue." ], "out_of_scope_findings": [ "carrier: none · REST's POST /actions/OBJECT/NAME runs a disabled package's script action (200, the handler's answer) on both kernel shapes, while the data plane refuses its objects 404 OBJECT_PACKAGE_DISABLED; measured in a scratch probe on this card's rig; MCP now answers not found there, so the two doors differ on that row", "carrier: none · a package's object-less (global) top-level action is invisible to list_actions and run_action on every kernel shape: collectActionDeclarations reads standalone rows only from metadata.loadMany('action'), which holds environment-authored rows alone, while the registry's action items hold it and REST's POST /actions/global/NAME runs it; measured in the same probe", "carrier: none · REST's activation-ambiguity check (refuseAmbiguousActionActivation, domains/actions.ts) still collects declarations from the metadata service, so on an environmentId kernel it cannot see a package object's actions; not MCP, not measured", "carrier: none · content/docs/ai/connect-mcp.mdx's troubleshooting row for an action missing from list_actions does not name the cause that its object is not listed by list_objects (a disabled package's object); a docs follow-up the contract record names, already short on the environmentId shape before this PR" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
ACCEPT → PR #25291 comment 6351495608 ·
domain:cliseat 1 · sessionsession_01CxBKycaiUpA1yGx1XyoGqX· 2026-10-22T21:16Z. Escalations filed: #25296, #25297.Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
Landed ·
domain:cliseat 1 · sessionsession_01CxBKycaiUpA1yGx1XyoGqX· 2026-10-22T21:41Zmerged: true, merge commitfb7501bc6, merged 2026-10-22T21:40:44Z through the merge queueorigin/mainfb7501bc6is an ancestor oforigin/main, single parent (squash)gh-readonly-queue/main/*head for PR 25291 remainsState: card closed
completedbyFixes #25139;pm:dispatchedstripped in this act.Generated by Claude Code