Repository navigation
ActionRunner: onSuccess.navigate passes an app-relative path to the console router verbatim, so '/object/id' lands on /_console/home; host it under the current app the way resolveNotificationTarget does #13379
Description
维护者速读
- 事由: 动作成功后的跳转
onSuccess: { navigate: '/crm_opportunity/${result.id}' }在控制台里落到/_console/home,而不是新记录。控制台把这个路径原样交给路由器,路由里没有它。 - 要做: 动作成功后的跳转,像收件箱通知链接一样,把不带应用段的路径放到当前应用下(复用
resolveNotificationTarget)。 - 完成标准: 不写应用 id 的跳转能打开当前应用里的那条记录;写了
/apps/…的跳转照旧。
Filing gate ③ a task the maintainer set: the maintainer's ruling on objectstack-ai/hotcrm#2247, recorded there at comment 6367379843 (director batch #6 item 1, letter C): 「同意」, 2026-10-23T14:34:48Z. Its item 2(a) orders this objectui card; item 2(b) orders the paired spec card, objectstack-ai/objectstack — number in the comment below. Filed by the repo:hotcrm seat 1 (os-elon-musk, session session_014xanhPEmGTMTfVH4UokwJT). ⛔ Not a claim.
Suggested grade: priority:p2 (the seat's reading; grade, domain:* and area:* are objectui triage's): spec-valid metadata that parses clean and then silently lands on the wrong page is the metadata-authoring trap class (c), with reach measured in a real browser below. A working spelling exists (the app-qualified path), which is why it is not p1.
Reader (who acts): objectui triage, then the domain:ui lane.
Governing text
- The ruling above, item 2(a): 「ask for the hop to host app-relative paths the same way」.
@objectstack/specsrc/ui/action.zod.ts,onSuccess.navigate(~:1763 on objectstackorigin/main2581efbcbd): "an in-app path starting with / or ./ (an SPA route hop)". Read the way an author reads it,/crm_opportunity/<id>is such a path; the console does not deliver it. The wording half is the paired spec card.
Measured
On @objectstack/* 18.0.0 (@objectstack/console 18.0.0), HotCRM origin/main c14ffde, in a real browser:
- An action with
onSuccess: { navigate: '/crm_opportunity/${result.id}' }succeeds. The runner hands/crm_opportunity/<id>to react-router, whose basename is/_console. That makes/_console/crm_opportunity/<id>, which matches no route, and the catch-all redirects to/_console/home. - The record's real route is
/_console/apps/<app segment>/<object>/record/<id>. - Installed code:
node_modules/@objectstack/console/dist/assets/framework-D2CDLHVn.js,ActionRunner.navigateOnSuccess→navigationHandler.
Where it lands (read on objectui origin/main 241cb78bd)
packages/core/src/actions/ActionRunner.tsnavigateOnSuccess(~:1874–1917): interpolatesnavigate, classifies the scheme, and callsthis.navigationHandler(url, { external, newTab })with the path unchanged.packages/react/src/context/ActionContext.tsx(~:123):onNavigatebecomes the runner'ssetNavigationHandler.packages/app-shell/src/hooks/useConsoleActionRuntime.tsxnavigateHandler(~:355–361):navigate(url), nothing else.- The precedent:
packages/app-shell/src/utils/appRoute.tsresolveNotificationTarget(~:328–343, objectui#5179) already sorts the same three shapes for the inbox: a scheme or//hostis external,/apps/…is already a console route, and anything else is hosted under/apps/<host app segment>. The card asks for the post-success hop to reuse that resolver (or one shared with it), ⛔ not a second copy of the rule. - Open question for the lane: hosting belongs where the current app is known (the console handler), not in
@object-ui/core, which has no app. Whethertype: 'url'targets take the same resolver is the lane's call; this card asks only foronSuccess.navigate.
Done when
- An
onSuccess.navigatewith no app segment opens the record in the current app:/crm_opportunity/record/${result.id}, and the shorthand/crm_opportunity/${result.id}, which the console already redirects to…/record/<id>once it is inside an app. - An app-qualified
/apps/<app>/…path, an external URL andmailto:behave as today. - A pin on the console's handler for each of the three shapes.
- After a release carrying it, Clone Opportunity stays on the source deal and the clone is found only through the list — give its result a View link, the way Generate Quote's does (#2194 R2-T1-U04) hotcrm#2247's hard-coded
'/apps/app.objectstack.hotcrm/crm_opportunity/record/${result.id}'may be shortened. The ruling calls that optional cleanup, not a task: the app-qualified spelling keeps working.
Size: S–M.
Dedupe
Method: every open objectstack-ai/objectui issue (36) and every issue updated since 2026-10-09 (697, any state), listed through the repo-scoped issues endpoint (paged by hand) on 2026-10-23, and matched case-insensitively on their titles; the search API is refused for this session. Words: onSuccess, navigate, navigation, app-relative, current app, ActionRunner, basename, redirectUrl. Nearest hits: #12755 (closed, the success toast after a url action), #12191 (closed, mailto: targets), #12338 (closed, a test row's onSuccess). None on point. New.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 23, 2026
Paired card: objectstack-ai/objectstack#25458 is the spec half that this card's body names (item 2(b) of the ruling on objectstack-ai/hotcrm#2247, comment
6367379843). It asks theonSuccess.navigatewording to match the console's app-qualified record route, or for an app-relative form that this card's resolver would serve. The two land in either order: this card makes today's app-relative spelling work, and the spec card makes the contract say so.Filed by the
repo:hotcrmseat 1 (sessionsession_014xanhPEmGTMTfVH4UokwJT). ⛔ Not a claim.Generated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
Claim: PM loop round 4 · 2026-10-23T15:38Z
Session:
session_01WJozybDmRH8z2c5SD7vJkj(domain:uiseat 1; an S card done by a sub-agent of this seat, dispatched by this project's coordinator)Account:
os-sales(the seat's linked user; the card's assignee)Branch:
claude/issue-13379-onsuccess-navigate-hostWorktree:
objectui-issue-13379Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/app-shell/src/hooks/useConsoleActionRuntime.tsx(the navigate handler),packages/app-shell/src/utils/appRoute.ts(only to shareresolveNotificationTarget's rule, never a second copy), tests beside,.changeset/(one changeset) (stop on breach; explain in the report)Container & model:
S,mode:subagent(a sub-agent of this seat, baseorigin/main),model: default,effort: medium(S)Clause-②: no
Responsibility: an action's
onSuccess.navigateto an app-relative path lands on Home instead of the record | any action with a post-success hop, every user | the user loses the record they just createdSerial constraints cleared: objectui#13384 (claimed in this act) lands in
@object-ui/core, not this handler; the paired spec wording card touches no objectui file; no open PR touches these paths (read in this act)objectstack-fleet commentedon Oct 23, 2026
LANDED
objectui#13379 由 PR objectui#13394 合入 main,合并提交
6183aa90f991bbe524244a85b694363b15019520(2026-10-23T16:34Z,经合并队列)。记录于 2026-10-23T16:34Z。Seat: domain:ui#1
落地内容:动作成功后的跳转
onSuccess.navigate写成不带应用段的路径(如/crm_opportunity/${result.id})时,控制台把它放到当前应用下打开,不再落到首页;/apps/…、外部链接、mailto:和应用之外的控制台路由照旧。记录页动作栏的同类问题另卡承接。合并时Closes已关本卡。撤下
pm:dispatched。席位核对见 PR comment 6369519309。fix(app-shell): host an app-relative onSuccess.navigate under the cur…