Skip to content

spec: ActionSchema gains outcomeMessages (a closed outcome key → I18nLabel, interpolating ${result.*}), and the client stops requiring message on the environments.delete answer (ruling A on cloud#2315) #21095

Description

@objectstack-fleet

Filing gate: ③ a maintainer-ruled task. The ruling is A on objectstack-ai/cloud#2315; the seat's analysis is cloud#2315 comment 5914904234. Recorded verbatim on that card. The maintainer's word was 「其他同意」: agreement to the recommended letter, given in the repo:cloud seat's session (session_01YSygzqVmrY31BnZge8KDo6) on 2026-10-01, with the decision batch presented in the director's format.

  • Who acts: triage routes it. It is a spec contract change, so the domain:spec lane is the expected home, with the client type in the same PR or a paired one.
  • Dedup: search_issues on objectstack for "action outcomeMessages outcome key success message interpolation result": 0 hits.

The ruling it executes

Ruling B on cloud#2315 (5731313414), not reopened: 「server returns facts, the console composes the message in the user's locale」. Ruling A on the mechanism: metadata-declared outcome copy. Three repos land it in order:

  1. this card (spec and client);
  2. objectui's renderer;
  3. cloud's three actions, LAST.

What to build (at objectstack main)

  • ActionSchema (packages/spec/src/ui/action.zod.ts): a new optional outcomeMessages, a map from a snake_case outcome key to an I18nLabel, valid for type: api | script.
    • The handler's answer carries a closed outcome string, and the console picks outcomeMessages[outcome]. Failing that, it uses successMessage, then the runner default.
    • successMessage (today a static I18nLabelSchema, around :1305) and each outcome message may interpolate ${result.*}. That is the scope onSuccess.navigate already declares in the same file, so there is no new dialect.
    • It joins strict schema and the liveness ledger like any new key. Translation bundles carry the outcome copy beside successMessage.
  • @objectstack/client (packages/client/src/index.ts): the environments.delete archive answer stops declaring message: string as REQUIRED (around :3165). It gains the outcome fact instead (archived | already_archived | purge_deferred | destroyed).

Why this shape (the measured pull)

  • ActionRunner composes dyn || action.successMessage || default (objectui packages/core/src/actions/ActionRunner.ts, around :1472). successMessage is static, so it cannot say which of delete's four outcomes happened. Three of those four destroy nothing, and cloud's sys-environment.object.ts and environment-delete-action.test.ts hold the invariant that a user can tell an archive from a destruction.
  • check_app_updates has three outcomes: updates_available | up_to_date | none_installed.
  • At least 6 more server-built English success messages exist in cloud routes (package-install.ts, package-review.ts) that the same mechanism serves.

Acceptance

  • The schema accepts outcomeMessages on api and script actions. It refuses an unknown shape loudly, and the liveness row is live (the console reads it).
  • A fixture action whose handler returns { outcome: 'archived', … } resolves to the archived copy, interpolated.
  • The client type no longer requires message.
  • The changeset names the new key. Clause-② yes: the public spec surface widens, so a contract-review record is owed.

Related

objectstack-ai/cloud#2315 (blocked on this card and on the objectui renderer card) · objectstack-ai/cloud#2435 (where export_package already dropped its message, PR objectstack-ai/cloud#2514).


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:i18nThe customer's own language, across UI, metadata and notificationsdomain:specenhancementNew feature or requestpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions