Repository navigation
Commit ecf56e7
fix(platform-objects): decide the hook panel's execution en-echoes per leaf, and pay round 5's cross-panel exclusion (#19530)
Part of #19403
Clause-②: no
Round 6 of #19403. The `hook` metadata-form panel's ten remaining
en-echoes, decided one leaf at a time, with the reason recorded for
each. **With them the panel is finished: zero of its 47 string leaves
now echoes its English source in all three locales.**
## The family, and why the leaf count did NOT decide it
Re-measured on this branch's base `0e671d20c` — the four remaining
families, in **both** counts:
| family | keys | leaves |
|:--|--:|--:|
| six bare type-display pairs
(`seed`·`mapping`·`api`·`doc`·`book`·`capability`) | 6 | **12** |
| `object.fields.enable.*` (+ `validations`) | 9 | 11 |
| **`hook.fields.retryPolicy.*` + `body.memoryMb` + `timeoutMs` ←
taken** | **5** | **10** |
| `report.fields.drilldown` + `runtimeFilter` +
`sections.dataset_binding` | 3 | 6 |
This family is **third of four by leaves**, so the tie-break is written
down — in the ledger's header and here. Two of the four reasons are ones
no other row can offer:
1. **It is the only family that makes the LANDED instrument stronger
rather than longer.** PR #19509's cross-panel invariant compares 5
shared `HookBodySchema` children × 2 props × 3 locales = 30 pairs and
**excluded 6 of them**, because `hook.fields.body.memoryMb` was itself
an en-echo and an unauthored twin carries no evidence. That file asserts
the exclusion by name and states that a later round of this card owes
it. Deciding `body.memoryMb` here **pays it**: the exclusion set is
empty, 30 of 30 pairs are compared, and `memoryMb` is guarded on both
panels. Ablation D reds that landed assertion, which is the proof the
discharge is real.
2. **It is the remaining half of a measured blind spot, on the panel
where the existing pin is blind through a control that is CORRECT.**
Round 5 measured `hookForm`'s enumerated-but-unwalked children at
**seven** — the five `body.*` plus `retryPolicy.maxRetries` and
`retryPolicy.backoffMs` — and closed the five on the `action` side only.
The two `retryPolicy` children are what was left.
3. **Evidence density forces per-leaf work**: `body.memoryMb` takes a
twin that exists only because round 5 created it; `timeoutMs` takes an
authored twin one level down the same panel at a byte-identical `en`;
`retryPolicy.*` has no twin anywhere and is composed from this catalog's
authored answers for its separate words.
4. **It completes a panel** — recorded as a reason that did **not**
decide, because `object` and `report` would complete theirs too.
And why **not** the six bare pairs, which lead by leaves: round 5's
refusal stands unchanged — only a real panel keeps the
DERIVED-POPULATION property with a working dark control, and six
unrelated types degenerate the derivation into six one-entry lookups
with nothing for the control to exclude.
## The ten decisions
Every verdict is `translate` in all three locales; every row records the
authored leaf its wording came from.
| leaf | `en` | zh-CN / ja-JP / es-ES | evidence shape |
|:--|:--|:--|:--|
| `body.memoryMb.label` | `Memory Mb` | 内存(MB) · メモリ(MB) · Memoria (MB)
| the twin **round 5 created** — copied verbatim |
| `body.memoryMb.helpText` | `Per-invocation memory cap (MB, max 256)` |
单次调用内存上限(MB,最大 256) · 呼び出しごとのメモリ上限(MB、最大 256) · Límite de memoria por
invocación (MB, máx. 256) | same twin; `256` kept as a numeral
(`ScriptBodySchema.max(256)`) |
| `timeoutMs.label` | `Timeout Ms` | 超时(毫秒) · タイムアウト(ms) · Tiempo de
espera (ms) | authored twin **one level down the same panel** |
| `timeoutMs.helpText` | `Abort the hook after N milliseconds` | 超过 N
毫秒后中止该钩子 · N ミリ秒経過後にフックを中止 · Abortar el hook después de N milisegundos |
the #19430 **near-miss**, cleared at the schema; `N` kept |
| `retryPolicy.label` | `Retry Policy` | 重试策略 · 再試行ポリシー · Política de
reintentos | composed from two authored answers in this catalog |
| `retryPolicy.helpText` | `Retry on failure — most useful for async
hooks` | 失败时重试——对异步钩子最有用 · 失敗時に再試行 — 非同期フックで特に有用 | `async` read at the
schema: a boolean, not a token |
| `retryPolicy.maxRetries.label` | `Max Retries` | 最大重试次数 · 最大再試行回数 ·
Reintentos máximos | extractor humanize rendered as the concept |
| `retryPolicy.maxRetries.helpText` | `Maximum retry attempts` |
最多可重试的次数 · 再試行の最大回数 · Número máximo de reintentos | the schema default
`3` deliberately **not** rendered |
| `retryPolicy.backoffMs.label` | `Backoff Ms` | 退避(毫秒) · バックオフ(ms) ·
Retroceso (ms) | `sys_job_queue.fields.backoff_type.label`'s authored
answer |
| `retryPolicy.backoffMs.helpText` | `Delay between retries (ms)` |
两次重试之间的延迟(毫秒) · 再試行間の遅延(ms) · Retraso entre reintentos (ms) | same
vocabulary; default `1000` not rendered |
**What was refused.** Four of the five labels are the extractor's
humanize of a camelCase key, not authored English — exactly where round
5's phantom-translation reading bites. `Memory Mb` → `Memory (MB)` or
`Max Retries` → `Max Retries (3)` would differ in bytes, **pass the echo
predicate in all three locales, drop the census by a key and tell a
zh-CN author nothing.** Every one is rendered into the locale's own
writing system instead, and the enumerated verdicts — not the census —
are what shows it.
## The #19430 discipline, and the near-miss this family had to clear
Read at the schema before a word was rendered, and **asserted against
the live `HookSchema`** rather than described:
- `timeoutMs.helpText` says "Abort the hook after N milliseconds", and
`abort` **is** a legal value of `HookSchema.onError`
(`z.enum(['abort','log'])`). The near-miss is real. It is **cleared**
because the key this tooltip describes takes a **number** — the schema
accepts `5000` and refuses `"5000 毫秒"` — so no rendered word can land in
it, and the schema's own description uses the word as the runtime's verb
("before the hook is aborted"). Rendered.
- `retryPolicy.helpText` names `async`. `HookSchema.async` is
`z.boolean().default(false)` — accepts `true`, refuses `"异步"` — so it is
**not** a #19430 token. Rendered, taking this panel's own authored 异步 /
非同期 / Asíncrono one entry up.
- `retryPolicy` is a `strictObject`, not an enum; its alias map governs
KEY spellings, which no label renders. Its defaults are `{maxRetries: 3,
backoffMs: 1000}` and neither tooltip carries a number — asserted both
ways.
- `N` and `256` are kept verbatim, and the token guard now judges
**Unicode word boundaries** rather than substring containment: `'Número
máximo de reintentos'.includes('N')` is `true`, so round 5's containment
check would have passed a locale that lost the placeholder entirely.
That is a control, and ablation E reds it.
## A second act: `body.capabilities` reworded on both panels
Round 5 **recorded rather than improved** that zh-CN 功能 and ja-JP 機能
read "feature" for what is a capability **token** from the
`HookBodyCapability` enum — and left the reword to the hook family,
because both forms declare the same schema key and diverging is the
defect the cross-panel invariant guards. This round is the hook family.
The replacement is **derived, not invented**: every authored leaf of the
objects catalog whose English names a capability renders it **能力**
(zh-CN) and **ケイパビリティ** (ja-JP), and none of them uses 功能 or 機能. The
ledger asserts that derivation over the catalog rather than quoting it.
es-ES already read `Capacidades` — the same word those leaves use — and
is **unchanged**, which is why the zh-CN and ja-JP bundle diffs are two
lines larger than es-ES's. The neighbouring senses
(`object.sections.capabilities` = 功能开关, the feature CHECKBOXES;
`agent.sections.capabilities` = 能力配置) are deliberately untouched and
pinned as such.
## The measurements, each with its control in the same run
| reading | base `0e671d20c` | head |
|:--|--:|--:|
| `en` string leaves / `.label` leaves | 893 / 538 | 893 / 538 — same
population |
| label keys echoing in ALL THREE | **23** ⇒ 69 `.label` leaves | **18**
⇒ **54** |
| POSITIVE CONTROL — labels genuinely translated | 515 · 499 · 499 |
**520 · 504 · 504** |
| decidable sibling remainder (label + its helpText/description) | 39 |
**29** |
| `hook` panel leaves echoing in all three | 10 of 47 | **0 of 47** |
Echoes −5 keys, control +5 in each locale, same population, same run.
**Two counts for two questions** — the headline moves by 5 because only
labels are counted, while this round decided 5 labels **and** 5
helpTexts.
- **No key added or removed.** Full flattened key sets, base vs head,
all four bundles: 893 / 893, 0 added, 0 removed — with a negative
control proving the comparator sees a one-key delta in both directions
(`hook.fields.__probe__.label`). `en` is untouched.
- **Regenerated with `pnpm i18n:extract`**, never by hand. It dropped
exactly the 10 decided leaves' provenance rows in each of the three
locales (30 rows, listed in full in the report comment) and **added
none**; the metadata-forms bundles round-tripped byte-identical.
- **Bundle diffs**: zh-CN 12/12, ja-JP 12/12, es-ES 10/10 — insertions
equal deletions in every bundle. The two extra lines per CJK bundle are
the `capabilities` reword on the two panels; es-ES needed none.
## The concurrent PR that held this region
**PR #19520 HAD LANDED** by the time of the pre-push merge — so the
required check was **not vacuous**, and it passes. Its leaf is
`view.fields.userFilters.helpText`, and in all three bundles this branch
carries `origin/main`'s value, not the base's:
```
base 快速筛选栏:控件样式(下拉 / 标签页 / 开关)+ 暴露的字段或标签页预设
main 快速筛选栏:控件样式(dropdown / tabs / toggle)+ 暴露的字段或标签页预设
head 快速筛选栏:控件样式(dropdown / tabs / toggle)+ 暴露的字段或标签页预设
```
`base != main` (the fix moved it) and `head == main` (it survived) hold
for `zh-CN`, `ja-JP` and `es-ES`. The merge brought its
one-line-per-bundle change in cleanly, exactly as the dispatch's
five-round measurement predicted. That changeset —
`19430-user-filters-element-tokens` — is **this card's own round-2
finding** coming back fixed by another seat, so silently reverting it
would have been this lane undoing its own filed work.
## The instrument — five ledgers extended, not rebuilt
`hook-execution-panel-echo-decisions.test.ts` carries every property the
five earlier rounds established, plus two this family added:
- the echo-reason rule as a **predicate with a dark control** (proved on
a synthetic row, since every verdict here is `translate`);
- the panel population **DERIVED** from the `en` catalog, with a dark
control naming keys that exist on other types — including `action`'s own
`body.memoryMb` at a byte-identical `en`;
- the **second witness** over the three `*.source-hashes.generated.ts`
companions, with its own pattern-matched dark control;
- the `en` source pinned **equal** to the live bundle, for the decisions
**and** the rewords;
- the **machine-token guard**, upgraded to Unicode word boundaries — the
new part, forced by a bare `N`;
- the **cross-panel invariant**, now at 30/30 with a `compared` counter
keeping it lit;
- the **composite blind spot** on the hook side, closed.
`action-body-panel-echo-decisions.test.ts` is updated in the same PR:
its exclusion set is emptied, its lit assertion becomes a counted 30,
and the prose that quoted the old capability wording now points at the
derivation behind the new one.
### Five ablations, ten assertions, two files
Each ran mutation → run → restore inside **one**
`scripts/ablation-replace.mjs` process, which proves the mutation landed
by blob hash and proves the restore by `blob == HEAD` plus an empty `git
diff HEAD`. No rebuild is involved: these tests resolve the bundles as
sibling sources, not through `dist`.
| # | mutation | assertions reddened |
|:--|:--|:--|
| A | re-fill `zh-CN hook.fields.retryPolicy.label` with its `en` |
`zh-CN: every decided leaf matches its verdict`; `no leaf on this panel
reads its en source…` |
| B | reword the `en` source under the pinned row | `every row is pinned
to the live en source`; `the echo predicate can say "echo"` |
| C | put a decided leaf's provenance row back | `zh-CN: no decided leaf
is still recorded as an extractor fill` |
| D | render `body.memoryMb` differently on the two panels | **round 5's
landed invariant** `the half NO single-panel pin can see`; `30 of 30
pairs agree`; `the invariant can fire` |
| E | drop the `N` placeholder from the es-ES tooltip | `the machine
tokens… are still verbatim`; `the token predicate can say NO` |
## Changeset — measured, not assumed
`@objectstack/platform-objects` is `private: false` with `files:
["dist", …]`, and the decided strings reach `dist`: each appears in
**6** built files, escaped (`\uXXXX` upper-case hex, and `\xNN` for
U+0080–U+00FF — `Pol\xEDtica de reintentos`). A **raw un-escaped
negative control** reads **0 including for the positive controls**, so a
zero in the raw column means "escaped", not "absent", and a
never-written string reads 0 in both columns. ⇒ a **`patch`** changeset;
`skip-changeset` is measurably wrong.
## Acceptance notes
**Zero cards to file, and that is a reading rather than a silence.** The
leaf that could have carried the known #19430 trap is
`hook.fields.timeoutMs.helpText`, whose `abort` **is** a real
`HookSchema.onError` enum value — it was checked at the schema, found to
describe a numeric key, and cleared, with the check asserted in the
ledger so a schema change reds it. `retryPolicy.helpText`'s `async` was
checked the same way and is a boolean. Neither is a defect, and neither
is a card.
Noted, not filed:
- **`hook.label` is `Gancho` in es-ES while every es-ES sentence on the
panel says `hook`** (`hook.sections.identity.description`,
`hook.fields.condition.helpText`, `hook.fields.async.helpText`, and now
`timeoutMs.helpText`, which copies that convention). This is a wording
inconsistency inside one panel, not a reproducible defect, not a
contract violation, and not a metadata-authoring trap — the author
writes neither word. Carrier: 无 (no PR or person is queued to touch this
file for it); it belongs to whichever round of #19403 takes a family
that renders the type's own display pair. Dedupe words: `es-ES`,
`Gancho`, `hook.label`, `metadata-forms`, `panel vocabulary`.
- **`permission.fields.systemPermissions.helpText` renders "system
capability keys" as システム機能キー in ja-JP**, which is the word this PR just
replaced for the hook body's capability tokens — but that leaf is a
*permission* capability, a different sense, and it is authored and
outside this family. Recorded so a later round does not read this PR's
reword as a sweep. Carrier: 无. Dedupe words: `ja-JP`, `機能`, `ケイパビリティ`,
`systemPermissions`, `capability wording`.
Neither carries `class: a|b|c` evidence, so by this round's reporting
contract both stay here as prose.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01NcPSwnmJHczmTu6FG7NMjE)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 61170fa commit ecf56e7
9 files changed
Lines changed: 990 additions & 76 deletions
File tree
- .changeset
- packages/platform-objects/src/apps/translations
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
62 | | - | |
63 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
64 | 66 | | |
65 | 67 | | |
66 | 68 | | |
| |||
216 | 218 | | |
217 | 219 | | |
218 | 220 | | |
219 | | - | |
| 221 | + | |
220 | 222 | | |
221 | 223 | | |
222 | 224 | | |
| |||
719 | 721 | | |
720 | 722 | | |
721 | 723 | | |
| 724 | + | |
722 | 725 | | |
723 | 726 | | |
724 | 727 | | |
| |||
735 | 738 | | |
736 | 739 | | |
737 | 740 | | |
| 741 | + | |
738 | 742 | | |
739 | 743 | | |
740 | 744 | | |
| |||
744 | 748 | | |
745 | 749 | | |
746 | 750 | | |
747 | | - | |
748 | | - | |
749 | | - | |
750 | | - | |
751 | | - | |
752 | | - | |
753 | | - | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
754 | 759 | | |
755 | 760 | | |
756 | 761 | | |
757 | | - | |
| 762 | + | |
758 | 763 | | |
759 | 764 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
567 | 567 | | |
568 | 568 | | |
569 | 569 | | |
570 | | - | |
571 | | - | |
| 570 | + | |
| 571 | + | |
572 | 572 | | |
573 | 573 | | |
574 | 574 | | |
| |||
582 | 582 | | |
583 | 583 | | |
584 | 584 | | |
585 | | - | |
586 | | - | |
| 585 | + | |
| 586 | + | |
587 | 587 | | |
588 | 588 | | |
589 | 589 | | |
| |||
594 | 594 | | |
595 | 595 | | |
596 | 596 | | |
597 | | - | |
598 | | - | |
| 597 | + | |
| 598 | + | |
599 | 599 | | |
600 | 600 | | |
601 | | - | |
602 | | - | |
| 601 | + | |
| 602 | + | |
603 | 603 | | |
604 | 604 | | |
605 | | - | |
606 | | - | |
| 605 | + | |
| 606 | + | |
607 | 607 | | |
608 | 608 | | |
609 | 609 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | 30 | | |
41 | 31 | | |
42 | 32 | | |
| |||
0 commit comments