Skip to content

Commit cc07862

Browse files
fix(automation, audit): runtime strings state each decision in words instead of a tracker number (stage 4) (#21472)
Part of #20751 Clause-②: no **Stage 4 of the `domain:services` lane under the maintainer's A / A ruling (5902360492): the `service-automation` and `plugin-audit` strings.** The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, error `code`, field, route, export or control flow moves (AST skeleton reads SAME for 10 of 10 changed sources, below). ## What this does The two packages' refusals, prescriptions, warnings, log lines, the `sys_automation_run` / `sys_flow_dispatch` field help and description, and the `sys_activity` `type` help (with its `es-ES`, `ja-JP` and `zh-CN` leaves) sent the reader to a tracker number for the reason behind them. In form D, as stages 1 to 3 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words. All 38 ledgered occurrences in this stage's surface (claim `5959898258`), re-derived from the ledger on `origin/main` at `9b7a0ef3`: `service-automation` 33 (25 pairs, 9 files), `plugin-audit` 5 (5 pairs, 5 files: `objects/sys-activity.object.ts` and its four `translations/*.objects.generated.ts`). They sit in 37 string sites. The sixth `plugin-audit` ledger entry, `audit-writers.ts` (one occurrence), is in a file excluded at file level (open PR #21436) and stays for a later stage. None of the three excluded files (`audit-writers.ts`, `stored-metadata-body-migration.ts`, `stored-metadata-hash-migration.test.ts`) is touched. ### Rewritten in words Author- and administrator-visible text first, log lines last. Line numbers are at the head. | Where | Cited | The text now says | Decision read from | |---|---|---|---| | `engine.ts:196-205`, the `fieldValues` refusal prescriptions on `create_record` and `update_record` | 2419 | "a runtime alias for it was rejected by design: the node keeps one strict `fields` key rather than two spellings" | 2419 is a pull request that proposed a `cfg.fields ?? cfg.fieldValues` alias in the executor; the design review declined it: correct the metadata at the source and keep a single strict `config.fields` contract | | `engine.ts:210-213`, the screen field `visibleIf` refusal prescription | 3528 | "A predicate under any other key is never read, so the field always shows — and a `required` field meant to stay hidden then blocks the screen from ever being submitted" | the card's root cause: a field visibility predicate never reached the client, so a `required` field the author meant to hide rendered unconditionally and the screen flow could not be submitted; `visibleWhen` went into the contract and is forwarded verbatim | | `engine.ts:10272-10274`, the undeclared-config-key refusal | 4045 | "the built-in node types were reconciled so every key their executors read is declared, and a read-but-undeclared key is exactly the drift that reconciliation removed" | 4045's closing: every built-in node publishing a `configSchema` got a Zod written from its executor and a two-way key-set reconciliation (CRUD, screen and map surfaced seven read-but-undeclared keys, all declared) | | `builtin/template.ts:192`, the unknown value-expression function error | 11060 | "An unknown function is refused here rather than evaluated to null, which would write the field as undefined" | the maintainer's ruling (option A): six functions mirrored 1:1 from CEL, and the silent `null` rewrite of an unknown function name became a loud, named error | | `sys-automation-run.object.ts:169`, `node_type` help | 3801 | "Keys the resume authorization gate, which decides from the paused node's type who may continue the run (an approval pause only through its owning service)" | the card's requirement, as `refuseGatedResume` enforces it: the gate is keyed on what the run is parked on; an `approval` pause continues only through `ApprovalService`, while a `screen` pause stays open to its flow runner | | `sys-automation-run.object.ts:234` `trigger_type` and `:288` `trigger_record_id` help | 7533 | "rows written before run history recorded its trigger (they were not backfilled)" | the card's ACCEPT: trigger columns written on terminal and paused rows; pre-existing rows carry none and rehydrate as "not recorded"; no backfill | | `sys-automation-run.object.ts:324`, `steps_json` help | 2585 | "the bounded per-node step log, so a finished run's per-node detail survives a restart" | item 3 of the card: durable single-run detail, a bounded step log persisted on terminal rows so a past run's detail survives a restart | | `plugin-audit` `objects/sys-activity.object.ts:116-121`, `type` help, and its four locale leaves | 11507 | "Consumers must render an unknown value instead of assuming this list is exhaustive: the vocabulary is open by decision, not a gap awaiting enforcement." | the maintainer's ruling (direction 4): the column is an open, author-extensible vocabulary, the declaration must say so, and every closed map over it is the bug | | `plugin.ts:1680-1689`, the inert-connector warning | 2612, 2977 | "entries without a `provider` are catalog descriptors (descriptor-only contract) ... An entry that names a `provider` is a connector instance instead: that provider's installed executor materializes it into a live connector (ADR-0097)" | 2612's resolution (descriptor-only contract, boot audit warning, `enabled: false` marks a catalog-only entry) and 2977's (ADR-0097 implemented: a provider-bound entry is materialized at boot by a generic executor). The old sentence said provider-bound instances were "tracked in" 2977, which has since landed; `findInertDeclaredConnectors` already skips provider-bound entries, which the new wording now says | | `plugin.ts:1143-1146`, debug | 1928 | "(flow conditions are checked against object fields at registration)" | 1928's closing: schema-aware condition validation at `registerFlow` through an opt-in object-schema resolver | | `plugin.ts:1184-1187`, debug | 3356 | "(a user-mode run carries the triggering user's positions and permission sets)" | 3356's resolution: `runAs:'user'` resolves the triggering user's positions and permission sets at run setup | | `plugin.ts:1214-1217`, debug | 3475 | "(a lookup the start node declares in expand is read with the run's own identity)" | 3475's plan as landed: opt-in start-node `config.expand`, expanded engine-side as the run's own identity so the referenced object's RLS/FLS holds | ### Citation only (the sentence already stated the decision) - `builtin/connector-nodes.ts:72` (3017, "Dispatch is unavailable until its upstream recovers; the platform retries automatically." — ADR-0097 quotes "the platform retries automatically", which stays verbatim). - `builtin/parse-config.ts:112` (4277, "config does not satisfy the X contract ... The declared contract is the node type's configSchema (the Studio form) and the X config Zod"). - `builtin/screen-nodes.ts:336` (1870, "no function named 'X' is registered. Register it via `defineStack({ functions })`, or fix the name"). - `engine.ts:181`, `:184`, `:187`, `:191`, the bulk-intent guidance (5393, "Bulk intent is `multi: true` ... so the concept keeps one name from node config to driver call ... a predicate write is refused by the engine rather than silently widened"; "Translating that declaration into `options.multi` on the engine call is the executor's job"). - `engine.ts:4026` (3017, "the materializer retries with backoff"). - `engine.ts:6069`, `:6073` (3760, 1888: "its data operations will be REFUSED ... Declare runAs:'system' ... a record-change flow fired by a system write carries no user either (ADR-0049)"). - `engine.ts:10268` (4277, "Flow 'X' rejected: N undeclared config key(s)"). - `engine.ts:11326` (4414, "The branch selection is IGNORED and every out-edge is evaluated instead ... mark the fallback edge `isDefault: true`"). - `runtime-identity.ts:113`, the `AUTOMATION_UNSCOPED_RUN_DATA_ACCESS` refusal (1888, 3760: "refusing a data operation ... would execute UNSCOPED ... Declare `runAs: 'system'`"; it keeps "(ADR-0049)"). Its `code` is unchanged. - `plugin.ts:1831`, `:2074`, `:2086`, `:2143` (3017: "pending retry cancelled", "until a retry succeeds", "retrying with backoff, attempt N", "next retry in Nms"). - `sys-flow-dispatch.object.ts:86` (10220, "one row per claimed dispatch key ... so a re-scan, a rebuilt kernel or an operator replay never re-launches a flow for a window it already delivered"). Every cited card (21: 1870, 1888, 1928, 2419, 2585, 2612, 2977, 3017, 3356, 3475, 3528, 3760, 3801, 4045, 4277, 4414, 5393, 7533, 10220, 11060, 11507) was read through REST, body and every comment, before its string was rewritten. 2419 is a pull request; its closing comment carries the decision. 11060 and 11507 answer 404 on the issue endpoint while their comment threads read normally; the rulings and dev reports in those threads carry the decisions. ### Translations - The `es-ES`, `ja-JP` and `zh-CN` `sys_activity.fields.type.help` leaves were byte copies of the English source, recorded as such in each locale's `*.source-hashes.generated.ts`. No translated text was written by hand: the three leaf values were emptied (key kept) and `node scripts/check-i18n-bundles.mjs --write --filter=plugin-audit` (the extract config's documented command, `--fill=default`) refilled them from the revised source, rewrote `en`, and recorded the three new digests. The same route the original ruling's PR took for these leaves. - All four leaves are byte-equal to the revised source description (440 characters each, checked against the string reassembled from `sys-activity.object.ts`). Tracker numbers left in the package's locale bundles: 0. ## Ledger (`scripts/doc-authoring-prose-id.baseline.json`) At dispatch no open PR held this file. While this branch was being built, PR #21462 (`domain:spec` stage 1 of #20749) opened and took it, so this PR waited: the branch was finished and green, and it was opened only after #21462 merged (`7e7e64b1`, about 40 minutes of waiting). Then `origin/main` at `7e7e64b1` was merged in (no rebase), and the ledger was recomputed on that tree with `node scripts/check-doc-authoring.mjs --census-ledger` (exit 0, no growth refusal) into a scratch file. The recomputed file is byte-identical to git's textual merge of the two sides. Against `main` the diff deletes 58 lines and adds none: exactly the 14 file blocks of this stage. Every other row is unchanged (a scripted comparison: 14 keys moved, all of them this stage's, each to absent). At PR-open time no other open PR touches the file. | | before | after | |---|---|---| | `service-automation` | 33 occurrences, 25 pairs, 9 files | 0 | | `plugin-audit` | 6 occurrences, 6 pairs, 6 files | 1 occurrence, 1 pair, 1 file (`audit-writers.ts`, excluded) | | whole ledger, on the tree first derived (`9b7a0ef3`) | 227 occurrences, 157 pairs, 62 files | 189, 127, 48 | | whole ledger, after `#21462` (`7e7e64b1`) | 174 occurrences, 127 pairs, 53 files | 136, 97, 39 | `pnpm check:doc-authoring` at the head: "sibling-package prose ids hold the baseline — 118 pinned site(s) across 39 file(s), 86309 string(s) read in 1253 parsed source(s), no growth, no burn-down unrecorded". No gate is added or loosened; `scripts/check-doc-authoring.mjs` is untouched. ## Changeset `.changeset/20751-services-strings-stage4-state-the-decision.md`: `patch` for `@objectstack/service-automation` and `@objectstack/plugin-audit`. Measured after building: the new sentences are in each package's built output (`service-automation` `dist/index.js` and `dist/index.cjs`; `plugin-audit` `dist/index.js` and `dist/index.mjs`). A TypeScript scan of every string literal and template text in the built output finds 0 tracker ids in `service-automation`, and 2 in `plugin-audit`, both the excluded `audit-writers.ts` occurrence (once per build format). Control: the same scan reads 86 in `plugin-security`'s built output. ## Text-only proof A TypeScript-AST skeleton of each changed non-test `.ts` file, where every string literal and template text is a placeholder, a run of adjacent string operands of a `+` chain is one string (only its embedded expressions are kept), identifiers and numbers keep their text, and comments are never read. `9b7a0ef3` against the head: 10 of 10 SAME (the two merges from `origin/main` touched neither package). Controls on scratch copies of `plugin.ts`, each mutation's marker counted once on disk first: a one-identifier rename reads DIFF; a text-only change reads SAME; a re-split of one template into two concatenated pieces reads SAME. ## Pins Assertions that found a message by its tracker number now find it by what it says. No `code` or `status` assertion was touched; none of these strings is a coded refusal. - `builtin/config-unknown-keys.test.ts:97`: the `visibleIf` prescription by "blocks the screen from ever being submitted" instead of the id. - `builtin/decision-branch-routing.test.ts:210`: the unclaimed-branch warning by "The branch selection is IGNORED" instead of the id. - `connector-degrade-cause.test.ts:185` and `:274`: the degrade error by "retrying with backoff, attempt 1." and the husk warning by "stays absent from the connector registry until a retry succeeds"; the three hand-built fixture messages in the same file (`:376`, `:396`, `:407`), which mirror the production text, drop the id too. - `connector-descriptor-audit.test.ts:134`: the inert-connector warning by "catalog descriptors (descriptor-only contract)". - `degraded-register-cause.test.ts:212`: the degraded-registration warning by "the materializer retries with backoff"; its fixture message (`:407`) drops the id. - `plugin-audit` `objects/sys-activity-type-open-vocabulary.test.ts` asserts the `type` help by three markers (`built-in`, `open vocabulary`, `ADR-0052`), all kept; no edit needed. The five edited test files were run with the verbose reporter (5 files, 50 tests passed) and every re-pinned case is listed as passed. ## Tests All through `scripts/pm/os-verify-lock.sh`, every verdict `VERDICT command-exit 0`, at the head `f300a255`: - Build: `turbo run build --filter=./packages/* --filter=./packages/*/*` (71/71). - `@objectstack/service-automation`: 166 files, 2053 tests passed; `@objectstack/plugin-audit`: 38 files, 618 tests passed. - `typecheck` for both, including `check:test-typecheck: OK` for each. ## Gates - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (no paths) at `f300a255` (24 paths vs merge base `7e7e64b1`, 195 changed lines): 74 commands, run one at a time from the worktree, each exit code recorded before any pipe; 74 exit 0. `--ran`: "74 derived famil(ies) accounted for — 74 run, 0 NOT-MEASURED (a DERIVED zero — all 74 recorded an exit code and none of them is 3)". The same 74 also ran green at `1af6bed2`, before the last merge. - `check:i18n`: "OK (9 package(s) — all bundles in sync, no undeclared authoring keys)"; `check:i18n-stale-fill`: "OK (10 bundle set(s) — no new stale fills, 0 baselined)"; `check-issue-citations`: "no issue citations added against 7e7e64b (17 file(s) read)"; `check:nul-bytes`: OK, 9807 files; `check:type-check-debt`: "none above its recorded number"; `check:dual-build-cjs-loads`: 105 require entry points across 66 packages load; `check:dts-closure`: 71 built packages, 167/167; `check:sourcemap-no-sources-content`: 68 packages, 524 maps; `check:published-files`: 69 publishable packages. - Outside the derived set, all exit 0 at `f300a255`: the eleven declared wide-population families (`check:init-service-contract`, `check:live-db-isolation`, `check:meta-type-normalized`, `check:optional-error-sink`, `check:resume-authority-declared`, `check:route-envelope`, `check:runner-env-posture`, `check:settings-bind-window`, `check:startup-registry-verdict`, `check:verify-stand-in`, `check:wildcard-fallthrough`) and the artifact-roster families whose roster sits under one of this PR's directories (`check-changeset-fixed`, `check-published-list-mirrors` and its self-test, `check:authz-resolver`, `check:console-injection`, `check:error-code-casing`, `check:filter-alias-parity`, `check:published-readme-exports`, `check-dts-references --self-test`; `check:engine-double-contract` and `check:i18n-stale-fill` are in the derived set). The path-scheduled CI jobs and the type-check lanes are CI's. - `pnpm lint` (`eslint . --no-inline-config`, repo-wide, not narrowed) at `f300a255`: exit 0. - `origin/main` moved by two commits after the ledger recompute (`49524f69`, `packages/rest`; `aa463223`, `packages/spec` and object-grid surfaces). Neither touches the ledger, `service-automation` or `plugin-audit`; the PR's CI merge ref and the queue carry them. ## Acceptance notes Noted, not filed: - `packages/runtime/src/domains/automation-put-post-error-parity.test.ts` (lines 57-70, assertion at line 247) and `automation-register-error-class.test.ts` (lines 87-100, assertion at line 308) each rebuild the undeclared-config-key refusal in a test fake, copied from `engine.ts` with both old ids, and assert `toContain` of the 4277 id on their own fake's message. They stay green (the fake is self-consistent) but no longer mirror the engine's text. `packages/runtime` is outside this stage's surface. Carrier: none. - `plugin-audit/src/audit-writers.ts` keeps its one ledgered occurrence (excluded file, open PR #21436); it is left for a later stage. - Two `plugin-audit` test files carry the 11507 id in failure-message text; test files are outside the ledger. --- _Generated by [Claude Code](https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0557c2f commit cc07862

24 files changed

Lines changed: 83 additions & 112 deletions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/service-automation': patch
3+
'@objectstack/plugin-audit': patch
4+
---
5+
6+
Automation refusals, prescriptions, log lines and run-object field help, and the activity type help, no longer cite tracker numbers; each one states the decision behind it in words
7+
8+
Clause-②: no
9+
10+
Some strings these two packages show to flow authors, operators and administrators pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
11+
12+
- `@objectstack/service-automation`: the refusal for a `fieldValues` write map says a runtime alias for it was rejected by design, so the node keeps one strict `fields` key; the refusal for a screen field's `visibleIf` says a predicate under any other key is never read, so the field always shows, and a `required` field meant to stay hidden then blocks the screen from ever being submitted; the undeclared-config-key refusal says the built-in node types were reconciled so that every key their executors read is declared; the unknown-function error in a flow value expression says such a name is refused rather than evaluated to null, which would write the field as undefined; the inert-connector warning says entries without a `provider` are catalog descriptors, while an entry that names a `provider` is a connector instance that provider's installed executor materializes; the `sys_automation_run` field help says the paused node's type decides who may continue a run (an approval pause only through its owning service), that rows written before run history recorded its trigger were not backfilled, and that a finished run's bounded step log keeps its per-node detail across a restart; three bridge debug lines say what each bridge provides. The bulk-intent guidance, the degraded-connector dispatch error and retry lines, the user-less `runAs` warning and refusal, the unclaimed-branch warning, the script-function and node-config refusals and the `sys_flow_dispatch` description drop their citations.
13+
- `@objectstack/plugin-audit`: the `sys_activity` `type` help, whose English text all four shipped locale bundles carry, says the vocabulary is open by decision, not a gap awaiting enforcement.
14+
15+
Text only: no status, error code, field, route or control flow moves. A client or log filter that matches the old text (for example a tracker-number suffix) needs the new spelling.

‎packages/plugins/plugin-audit/src/objects/sys-activity.object.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ export const SysActivity = ObjectSchema.create({
117117
+ 'vocabulary, not a closed enum: metadata authors may contribute their own values '
118118
+ '(sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an '
119119
+ 'undeclared value is stored verbatim rather than rejected. Consumers must render '
120-
+ 'an unknown value instead of assuming this list is exhaustive (maintainer ruling '
121-
+ '2026-08-24, #11507).',
120+
+ 'an unknown value instead of assuming this list is exhaustive: the vocabulary is '
121+
+ 'open by decision, not a gap awaiting enforcement.',
122122
required: true,
123123
readonly: true,
124124
searchable: true,

‎packages/plugins/plugin-audit/src/translations/en.objects.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
122122
},
123123
type: {
124124
label: "Type",
125-
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive (maintainer ruling 2026-08-24, #11507).",
125+
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive: the vocabulary is open by decision, not a gap awaiting enforcement.",
126126
options: {
127127
created: "created",
128128
updated: "updated",

‎packages/plugins/plugin-audit/src/translations/es-ES.objects.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
122122
},
123123
type: {
124124
label: "Tipo",
125-
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive (maintainer ruling 2026-08-24, #11507).",
125+
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive: the vocabulary is open by decision, not a gap awaiting enforcement.",
126126
options: {
127127
created: "Creado",
128128
updated: "Actualizado",

‎packages/plugins/plugin-audit/src/translations/es-ES.source-hashes.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
export const esESGeneratedSourceHashes: Readonly<Record<string, string>> = {
2121
"objects.sys_activity.fields.actor_id.label": "b155813f8a7f06e3",
22-
"objects.sys_activity.fields.type.help": "bc8b10c89aacd494",
22+
"objects.sys_activity.fields.type.help": "5d8df777db464241",
2323
"objects.sys_activity.fields.url.label": "2203b0b9f72534f7",
2424
"objects.sys_audit_log.fields.actor.label": "b155813f8a7f06e3",
2525
};

‎packages/plugins/plugin-audit/src/translations/ja-JP.objects.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
122122
},
123123
type: {
124124
label: "タイプ",
125-
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive (maintainer ruling 2026-08-24, #11507).",
125+
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive: the vocabulary is open by decision, not a gap awaiting enforcement.",
126126
options: {
127127
created: "作成",
128128
updated: "更新",

‎packages/plugins/plugin-audit/src/translations/ja-JP.source-hashes.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
*/
1919

2020
export const jaJPGeneratedSourceHashes: Readonly<Record<string, string>> = {
21-
"objects.sys_activity.fields.type.help": "bc8b10c89aacd494",
21+
"objects.sys_activity.fields.type.help": "5d8df777db464241",
2222
"objects.sys_activity.fields.url.label": "2203b0b9f72534f7",
2323
};

‎packages/plugins/plugin-audit/src/translations/zh-CN.objects.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
122122
},
123123
type: {
124124
label: "类型",
125-
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive (maintainer ruling 2026-08-24, #11507).",
125+
help: "Activity kind. The declared options are the platform BUILT-IN set of an open vocabulary, not a closed enum: metadata authors may contribute their own values (sanctioned channel: `activityMilestones[].type`, ADR-0052 §5b.2), and an undeclared value is stored verbatim rather than rejected. Consumers must render an unknown value instead of assuming this list is exhaustive: the vocabulary is open by decision, not a gap awaiting enforcement.",
126126
options: {
127127
created: "已创建",
128128
updated: "已更新",

‎packages/plugins/plugin-audit/src/translations/zh-CN.source-hashes.generated.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
*/
1919

2020
export const zhCNGeneratedSourceHashes: Readonly<Record<string, string>> = {
21-
"objects.sys_activity.fields.type.help": "bc8b10c89aacd494",
21+
"objects.sys_activity.fields.type.help": "5d8df777db464241",
2222
"objects.sys_activity.fields.url.label": "2203b0b9f72534f7",
2323
};

‎packages/services/service-automation/src/builtin/config-unknown-keys.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ describe('unknown node config keys are rejected (#4277)', () => {
9494
// …and this particular key has a documented incident, so it also carries
9595
// its tombstone (the UNKNOWN_KEY_GUIDANCE pattern).
9696
expect(msg).toContain('visibleWhen');
97-
expect(msg).toContain('#3528');
97+
expect(msg).toContain('blocks the screen from ever being submitted');
9898
// The flow is NOT registered.
9999
await expect(engine.getFlow('f')).resolves.toBeNull();
100100
});

0 commit comments

Comments
 (0)