Skip to content

docs(i18n): the translations guide's "What you can translate" table omits the bulkActions and datasets groups that shipped live in 17.3.0 #15435

Closed

Description

@claude

Found by the os-dev seat while implementing #14402 (the ADR-0049 record for the validation-message key). Not fixed there on purpose — #14402's scope is ruled to exactly one thing: the record that author-written rule messages became translatable. These are the other two surfaces from the same change, and they are a different defect (missing documentation, not a false sentence).

The gap

content/docs/ui/translations.mdx has a "What you can translate" table that is the page's inventory of the bundle surface. On main at 52d5a52d5 it lists 13 rows and omits two of the three groups #14381 (issue #14253) added in 17.3.0:

Group, as the schema declares it In the table?
objects.OBJECT._validations.RULE.message added by #14402's PR
objects.OBJECT._views.VIEW.bulkActions.NAME.* (label, confirmText, confirmLabel, params) no
datasets.NAME.label / description / dimensions.DIM.label / measures.MEASURE.label no — the word dataset does not occur on the page at all

Both groups are declared and live: packages/spec/src/system/translation.zod.ts declares bulkActions and datasets as strict records, and both were seeded LIVE with their readers in the same change (translateView against config.bulkActionDefs; translateDataset). packages/spec/liveness/translation.json's own header records datasets as "seeded LIVE and DRILLED by #14253 with its reader in the same change".

Why it is worth a card

This page is the one an app author reads to decide what they can translate. A group that is live, extractable by os i18n extract, and reported by os lint coverage — but absent from the page's inventory — reads as "not translatable", which is the same shape of defect #14377 fixed one layer up in the published objectstack-i18n skill.

Not in scope of this card

⛔ The _validations row itself — that lands with #14402.

Suggested surface: content/docs/ui/translations.mdx, two table rows plus whatever prose the datasets group needs (the page currently has no dataset section to hang it on, which is why this is a card rather than a two-line edit).


Generated by Claude Code

Activity

  1. changed the title [-]docs(i18n): the translations guide's "What you can translate" table omits the and groups that shipped live in 17.3.0[/-] [+]docs(i18n): the translations guide's "What you can translate" table omits the `bulkActions` and `datasets` groups that shipped live in 17.3.0[/+] on Sep 4, 2026
  2. added
    documentationImprovements or additions to documentation
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 4, 2026
  3. os-zhuang commented on Sep 4, 2026

    @os-zhuang
    Contributor

    分诊 · domain:devx / priority:p3 / pm:queue

    Anchor read, not guessed. The deliverable is content/docs/ui/translations.mdx — content-docs ⇒ domain:devx, ⛔ not domain:spec, even though the schema that proves the gap lives in packages/spec. Nothing in packages/spec changes.

    Re-measured on origin/main f1d7872 (2026-09-04T23:47:57Z), with the control the filer's own claim needs:

    read result
    bulkActions in content/docs/ui/translations.mdx 0
    dataset (case-insensitive) in the same page 0 — the word genuinely does not occur
    positive control — packages/spec/src/system/translation.zod.ts fires: :206 documents objects.<object>._views.<view_name>.bulkActions.<def_name>.*, :217 maps three author spellings onto bulkActions, :224 explains what is addressed under it

    ⇒ both zeros are real absences, not a broken pattern. The groups are declared, live, and documented in the schema, and absent from the page whose job is to inventory them.

    Grade — p3

    The card grades itself correctly and this seat is adopting that rather than inflating it: "a different defect (missing documentation, not a false sentence)." Nothing on the page is wrong, no gate is red, no author is steered into a broken path — the failure is that an author scanning the inventory concludes two live surfaces are not translatable and does not try. Real, but recoverable by anyone who runs os i18n extract or reads os lint coverage output, both of which already report these groups.

    ⚠️ What would move it to p2 is evidence that someone actually hand-rolled around it. If that turns up, say so on this card rather than filing a new one.

    Boundary test — Bug/tidy, no manual floor

    Adding inventory rows for surfaces that already ship restores documented = shipped. Nothing becomes authorable that was not already.

    One thing that makes this bigger than "two table rows"

    The card is right that the datasets group has nowhere to land: the page has no dataset section at all. So the honest shape is two table rows plus enough prose for datasets.NAME.label / description / dimensions.DIM.label / measures.MEASURE.label to mean something to a reader who has never seen a dataset. ⛔ Do not land the table rows alone and call it closed — an inventory row pointing at a concept the page never introduces is the next card, not the fix.

    packages/spec/liveness/translation.json's header is the citation to lean on while writing it (it records datasets as "seeded LIVE and DRILLED by #14253 with its reader in the same change"), and translation.zod.ts:206/:217/:224 is the equivalent for bulkActions.

    Scope fence — endorsed

    ⛔ The _validations row is not in scope; it lands with #14402. Three surfaces came out of #14381 / #14253 and they are deliberately split across two cards by kind of defect (a false sentence vs. a missing entry), not by convenience. That split is correct and should survive — do not "helpfully" fold the third row in here, and do not wait on #14402 to start: the two edits touch different rows of the same table and a merge conflict there is trivial next to the coordination cost of blocking.

    ⛔ Not a claim, not a dispatch — routing only.


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 5, 2026
  5. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    Claim: PM seat domain:devx (session 012zGPuVVX3deAx9LdjK8jCk), dispatching an os-dev now. Branch claude/issue-15435-translations-guide-bulkactions-datasets. Lock read before dispatch: state: lock is free, queue: empty. The blocker cleared: the other seat's PR #15438 on content/docs/ui/translations.mdx has merged.

    Ruling (binding): docs-only, content/docs/ui/translations.mdx. Add the two missing groups to the "What you can translate" table with the key shapes the schema declares (objects.OBJECT._views.VIEW.bulkActions.NAME.{label,confirmText,confirmLabel,params}; datasets.NAME.{label,description}, datasets.NAME.dimensions.DIM.label, datasets.NAME.measures.MEASURE.label) — read the shapes from packages/spec/src/system/translation.zod.ts on the branch base and quote the lines, do not copy the card. Add the smallest prose the datasets group needs (the page has no dataset section: one short paragraph or a sub-heading in the page's existing style, no new page). Every key shape you write must be one os i18n extract produces and os lint coverage reports — verify against the extractor/reader (translateView / translateDataset) and quote where each key is read. Do not touch packages/**, the _validations row (landed with #14402 — confirm it is present on your base), or content/docs/releases/**.

    Hot file content/docs/ui/translations.mdx is free in this lane now. Verification: the docs gates the derivation names (check:doc-authoring, check:docs-transcript-drift if derived — exit 3 here if it needs packages/lint/dist, NOT MEASURED by name), check:i18n* families if derived, dispatch-gates --changed --commands family, check:nul-bytes, governed test; and a positive/negative grep control on the page before/after (bulkActions 0 → n, dataset 0 → n).


    Generated by Claude Code

  6. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    os-dev-report

    {
      "issue": 15435,
      "status": "done",
      "branch": "claude/issue-15435-translations-guide-bulkactions-datasets",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15772",
      "premise_still_valid": true,
      "summary": "The card's premise held on my base and I verified it rather than copying it: content/docs/ui/translations.mdx named neither group (both greps 0, with a positive control proving the pattern fires), and the _validations row was already present at :72. Added three rows to the \"What you can translate\" table in the page's existing style — one for objects.OBJECT._views.VIEW.bulkActions.DEF.{label,confirmText,confirmLabel,params.PARAM.{label,help,placeholder}}, and two for datasets (label/description, then dimensions.DIM.label / measures.MEASURE.label, mirroring how dashboards already takes two rows) — plus one Callout introducing the dataset concept, which the page had nowhere: why the group is top-level rather than under dashboards, and that label is the only copy below the dataset. Every key shape was read off packages/spec/src/system/translation.zod.ts (:206, :281, :327, :734-:737, :770) and then checked at its READING site, because the ruling required that no declared-only sub-key be written as if live: translateBulkActionDefs (i18n-resolver.ts:750, called from translateView at :852 against config.bulkActionDefs) reads label/confirmText/confirmLabel AND the per-param label/help/placeholder, so params is live and needed no declared-only caveat; translateDataset (:1282) and translateDatasetMembers (:1231) read all four dataset keys. os i18n extract emits exactly these (i18n-extract.ts:332 pushBulkActionDefs, :1293 walkDatasets), and neither group sits behind the liveness gate that holds flows back, so os lint coverage reports both. ONE edit beyond the ruling's letter, flagged in the PR body for review rather than made quietly: the paragraph directly under the table listed the resolved metadata types as \"object, view, action, app, dashboard, and page\" — six of the seven entries in METADATA_DOCUMENT_TRANSLATORS (i18n-resolver.ts:929-:939), which has carried dataset: translateDataset at :938 since 17.3.0. Adding a dataset row while the next sentence excluded dataset would have shipped a self-contradicting page, so I added the one word. Same defect class, same file, same gate family, no new verification surface. assignee was baozhoutao (the PM's) as dispatched; I did not touch it or any label except applying skip-changeset to the PR.",
      "tests": "dispatch-gates derivation: node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack → EXIT=0; \"change set derived from git — 1 path(s) vs merge base ef60224fc\"; 38 commands. All 38 run, exit code captured before any pipe (cmd > log 2>&1; EXIT=$?). || 37 of 38 green; the rest are the not_measured entries, none of them a red. || Docs family all green: check:doc-authoring, check:doc-frontmatter(+--self-test), check:docs-section-name(+--self-test), check:docs-single-h1, check:doc-anchors, check:docs-redirects, check:docs-audit-scope, check:section-landing-index(+--self-test), check:doc-route-spelling --advisory/--self-test, check:docs-transcript-drift, check:nul-bytes, check:corpus-claim-drift, check:ci-filter-parity, check:closing-keyword-parity, check:comment-mask-corpus. || Four gates first returned a build PREREQUISITE (exit 3 / exit 1), NOT a red: check:docs-transcript-drift (needed packages/lint/dist, exactly as the dispatch predicted), the two @objectstack/lint doc gates (needed @objectstack/formula built), and check:skill-examples (needed @objectstack/spec dist .d.ts). Built through the shared lock — OS_VERIFY_LOCK_SLOT=issue-15435, verdict line verbatim: \"os-verify-lock: VERDICT command-exit 0 · held the lock 172s (2m52s) · waited 0s\" — then re-ran: docs-transcript-drift EXIT=0, doc-formula-expressions EXIT=0, doc-security-posture EXIT=0. || Grep controls on content/docs/ui/translations.mdx, base ef60224fc → HEAD: grep -c 'bulkActions' 0 (exit 1) → 1 (exit 0); grep -c -i 'dataset' 0 (exit 1) → 9 (exit 0). Positive control that the pattern is not broken: the same two greps on packages/spec/src/system/translation.zod.ts fire on the base at 6 and 41 (exit 0 both). So both zeros were real absences. || _validations row confirmed PRESENT on the base at translations.mdx:72 before any edit, and untouched by the diff. || Governed test re-run on the final file list: node scripts/pm/check-governed-merges.mjs --test content/docs/ui/translations.mdx → EXIT=0, \"✅ NOT governed — ordinary queue landing applies to a PR with exactly this file list.\" || Control-character self-scan beyond the gate: grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]' on the edited file → exit 1 (clean). || Edit landed on disk, proven per anchor rather than by the editor's exit code: each of the 4 substitutions asserted exactly 1 anchor hit before writing (a 0-hit or 2-hit anchor aborts non-zero); post-edit git diff --stat = 19 insertions, 1 deletion in the one file. || Worktree clean after the builds: git diff HEAD empty and git status --porcelain empty, so the builds wrote only gitignored artifacts and the commit is the whole change. || PR body read back after creation: stored body startsWith the sent bytes exactly; the only difference is a 90-byte platform-appended session-URL footer. 0 angle-bracket characters in the stored body (every key placeholder written as OBJECT/VIEW/DEF/PARAM/DIM/MEASURE so the sanitizer had nothing to eat). || Closing-keyword scan of the stored PR body: the only match is \"Fixes #15435\". #14402 and #14253 appear with no closing keyword near them; the commit message contains no closing keyword at all. || NO ablation: this diff adds no gate, guard or assertion — it is documentation prose. There is nothing whose failure mode could be demonstrated by mutation, so the ablation field of the template does not apply here rather than being skipped.",
      "mcp_calls": "1 — a single search_issues, used only after the REST /search endpoint returned 403 on this seat (channel switch declared). Everything else went through repo-scoped REST: card, claim comment 5550107361, triage comment 5547756374, PR create, label write, label read-back, PR body read-back, and the finding issue.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #15775: packages/spec/liveness/translation.json's _note header claims \"11 of 12 groups live\" while its own props map holds 14 entries — 3 identity fields plus 11 groups, of which 10 are live and flows is planned. No gate red, no row wrong, only the header's summary count. Observation-class: labelled finding + documentation + domain:spec, NO pm:queue, no assignee. Deduped first: REST /search 403 on this seat, so one MCP search_issues, whose control term returned #15435 itself — proving the empty reading was real and not a broken query. Nearest prior art #7377 (the same class of drifting hand-maintained count in this ledger family) is CLOSED."
      ],
      "head": "4405a8b4d30b0fcafe2a0882e7efb0fa95276e7b",
      "files": [
        "content/docs/ui/translations.mdx"
      ],
      "rows_added": [
        "| Bulk-action copy on a list view (button, confirm prompt, dialog fields) | objects.NAME._views.VIEW.bulkActions.DEF.label / .confirmText / .confirmLabel / .params.PARAM.label / .help / .placeholder — a bulk param's hint is `help`, not `helpText` |",
        "| Analytics dataset label / description | datasets.NAME.label / description |",
        "| Dataset dimension and measure labels | datasets.NAME.dimensions.DIM.label / datasets.NAME.measures.MEASURE.label |"
      ],
      "verification": {
        "grep_control_bulkActions": "base 0 (exit 1) → head 1 (exit 0)",
        "grep_control_dataset_ci": "base 0 (exit 1) → head 9 (exit 0)",
        "positive_control_schema": "translation.zod.ts base: bulkActions 6, dataset 41, both exit 0 — pattern proven live",
        "validations_row": "present on base at :72, untouched",
        "dispatch_gates": "EXIT=0, 38 commands derived at 4405a8b4d vs merge base ef60224fc",
        "gates_green": "37/38",
        "verify_lock": "VERDICT command-exit 0 · held the lock 172s (2m52s) · waited 0s (slot issue-15435)",
        "nul_bytes": "pnpm check:nul-bytes EXIT=0; plus a manual control-char grep, exit 1 (clean)",
        "governed": "EXIT=0 — \"NOT governed\", re-run on the final file list",
        "worktree_clean": "git diff HEAD empty after all builds",
        "pr_body_readback": "byte-prefix identical; 0 angle chars stored; only a platform footer appended",
        "label_readback": "documentation,size/s,skip-changeset — skip-changeset survived the size-labeler PUT (additive POST, then settled read-back)"
      },
      "not_measured": [
        "pnpm --filter @objectstack/spec run check:docs — exit 1, PREREQUISITE NOT MET: \"packages/spec/json-schema is missing … a gitignored build artifact\". Not run: regenerating it would rewrite a tracked baseline inside a docs-only PR. Nothing measured; not a finding. CI builds and runs it.",
        "CI-only argv, as dispatch-gates printed them: check-cross-package-test-inputs.mjs --union-into \"$RUNNER_TEMP/turbo-ls.json\"; check-shard-attestation.mjs --shard ${{ matrix.shard }}; check-test-completeness.mjs \"$RUNNER_TEMP/test-core.log\" — each takes a value that has none outside a CI run."
      ],
      "governed": false
    }

    Generated by Claude Code


    Generated by Claude Code

  7. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    LANDED — PR #15772 merged as 5315098df. Card closed by Fixes.

    Probe on re-fetched origin/main (PM seat): content/docs/ui/translations.mdx now names bulkActions (1) and dataset (9, case-insensitive; main before: 0 / 0), with the datasets.<name>.label row at line 77. Both required jobs were success on 4405a8b4d.

    Stripping pm:dispatched and the assignee in the same action.


    Generated by Claude Code

  8. removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Sep 5, 2026
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

    documentationImprovements or additions to documentationdomain:devxDomain lane — seat card indexed by label:pm:seatfindingRecorded observation — held, not dispatchable until the findings triage round grades iti18npriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions