Skip to content

ActionRunner's legacy ActionDef.onSuccess chained-callback channel is unreachable from validated metadata and has zero producers #5934

Description

@claude

Filed unassigned by the dev seat implementing #5221 (session 01EuPCi56cnGyykygi3z9w4m, branch claude/issue-5221-onsuccess-navigation, PR #5933). Observation, not a claim on anyone's time — recording a measurement so the next reader does not have to retake it.

Duplicate-checked against the repo-scoped open-issue listing (222 open issues scanned; /search/issues is unavailable in that environment): the only other cards naming this key are #5221 (the console navigation half, now implemented) and #5493 (the four renderer surfaces that drop the key). Neither covers the channel below.

What was measured

packages/core/src/actions/ActionRunner.ts declares a runtime meaning for onSuccess that predates the spec key:

323: onSuccess?: ActionDef | ActionDef[];

read at the end of handlePostExecution and run through executeChain. Two facts about it, both measured on 0fce2ef81:

1 — it is unreachable from validated metadata.@objectstack/spec declares ActionSchema.onSuccess as a closed strict object { navigate: string, openIn: 'self' | 'newTab' }. A callback-shaped value is refused at parse. Against the installed pin:

ActionSchema.safeParse({ …, onSuccess: { navigate: '/x', bogus: 1 } })
→ success: false, issue code: unrecognized_keys

So no author can put an ActionDef there and have it survive publish/save.

2 — it has zero producers in this repo. Every onSuccess: writer outside ActionRunner's own unit test is a React/form callback function on a different surface (plugin-form's ObjectFormSchema.onSuccess?: (data) => void and friends — onSuccess: handleFormSuccess), not an ActionDef. The only two writers of the ActionDef shape are in packages/core/src/actions/__tests__/ActionRunner.test.ts:

1028: onSuccess: { type: 'notify', params: { msg: 'ok' } },
1056: onSuccess: [{ type: 'cb1' }, { type: 'cb2' }],

Why record it

Two meanings now share one key on one runner. PR #5933 tells them apart by the spec's own declaration — a non-array object whose navigate is a string is the spec block, everything else falls through to the callback channel — and pins that the callback channel still runs. That discrimination is sound but it is a standing cost: every future reader of that line has to hold both meanings, and the ADR-0087-style hazard from interpolateTarget's own docblock applies here too — if a spec loosening ever admits a shape closer to an ActionDef, the split becomes ambiguous.

The long-term-correct move is probably to retire the callback channel, leaving onSuccess with exactly the meaning the contract declares. It was deliberately not ridden into #5933:

  • ActionDef is an exported type of @object-ui/core, so removing a member is a breaking change to the published library, not an internal tidy;
  • it lands in packages/core, outside that card's fence;
  • and a dead verdict on a runtime channel wants the liveness discipline applied deliberately, not as a rider on a feature PR.

Not asserting a verdict

This is filed as an observation. Whether the channel is genuinely dead, whether a downstream consumer outside this repo uses it, and whether removal is worth a major are all triage questions — the point of the card is that the measurement exists and the two meanings are now documented at the code.

Refs: #5221 · #5933 · #5493


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfinding

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions