Skip to content

sys_position's shipped en bundle still asserts installation-wide uniqueness that #8556 corrected at source #8601

Closed

Description

@os-zhuang

Measured during #8554 / PR #8599, on origin/main.

#8556 (landed 6b441a84) corrected sys_position's published uniqueness claim at source — the spec describe() went from "Unique position name" to "Position name, unique per organization", and the generated reference page was regenerated from it.

The translation bundle was not updated, and main currently ships the old claim. packages/plugins/plugin-security/src/translations/en.objects.generated.ts still reads "Unique machine name for the position" — so the corrected source and the English text an admin actually reads in Setup disagree, right now.

Why the gate did not catch it

check-i18n-bundles.mjs --write printed regenerated for all nine packages and changed nothing, and check:i18n reports all bundles in sync either way. That is #8543 — the merge mode never updates an existing field description, so editing one leaves the bundle silently stale with the gate green.

This card is the data residue, not the generator defect. It does not need #8543 to land first: the bundle header documents the workflow — "Edit translations in place; re-run extract (with --merge) to fill new gaps. Do not hand-edit the structure — only the leaf string values" — and PR #8599 used exactly that route for its own five objects, correcting the leaf values in all four shipped locales.

What to do

Correct sys_position's leaf values in all four shipped locales (en, es-ES, ja-JP, zh-CN) to match the source describe() that #8556 landed. Leaf values only; ⛔ do not hand-edit the structure, and ⛔ do not touch the generator (that is #8543's).

⚠️ Worth sweeping while there: #8556 was one card. Any other landed source correction whose bundle went stale the same way has the same residue, and the gate will not tell you. A short sweep for bundle strings that contradict their current source describe() would bound it.

Related

Filed by the domain:metadata PM seat.

Activity

  1. added theissue type on Aug 14, 2026
  2. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor

    Triage confirmation: native type Bug set (the shipped en bundle contradicts the corrected source describe() — declared vs shipped, measured on origin/main). Labels accepted as filed.

    Routing note, recorded deliberately: the leaf edits land in packages/plugins/plugin-security translation bundles, which by the bare anchoring rule would read domain:identity — the card stays domain:metadata because it is the data residue of that lane's own in-flight sweep (#8554 / PR #8599) and shares its exact file surface; splitting one in-flight bundle surface across two lanes would defeat batch independence. Hard same-file serial: land after PR #8599.


    Generated by Claude Code

  3. self-assigned this
    on Aug 14, 2026
  4. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor

    Claim: PM loop round 1 (concurrency raised to 5 by the maintainer mid-round)
    Session: session_01XeQRiAa7vYRVX5Fog7Zby8
    Branch: claude/issue-8601-sys-position-bundle-locales
    Worktree: objectstack-issue-8601
    Domain: domain:metadata
    File surface: packages/plugins/plugin-security/src/translations/{es-ES,ja-JP,zh-CN}.objects.generated.ts — leaf values only, sys_position.fields.name.help (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — S by size but not mechanical: check:i18n reports green either way (that is #8543, this card's own explanation for how the drift survived), so no gate decides correctness here and the translation judgement is load-bearing. Tiering rule for a non-mechanical S card is M treatment.
    Serial constraints cleared: triage's «land after PR #8599» is discharged — #8599 merged as b45c71e. No open PR touches plugin-security. Batch siblings are in driver-sql, platform-objects, metadata-protocol and objectql; disjoint by package.

    ⚠️ Premise re-measured before dispatch — the card is half dead, and the scope changes

    The card states that en.objects.generated.ts "still reads «Unique machine name for the position»". That is no longer true on origin/main. Grep for that string returns zero — and the zero is not vacuous: sys_position is present in the same file at :12, and «per organization» appears there 4 times. The en leaf at :22 now reads:

    help: "Machine name for the position, unique per organization (e.g. sales_manager, hr_specialist)"

    which matches the corrected source at sys-position.object.ts:183-185 verbatim. The en half of this card is already delivered.

    The other three shipped locales are still stale, so the card's substance survives — and they are stale in two ways, asserting unqualified uniqueness and carrying superseded examples:

    locale shipped today
    es-ES "Nombre técnico único del puesto (p. ej. admin, editor, viewer)." «único», unqualified
    ja-JP "ポジションの一意の機械名(例: admin、editor、viewer)" 「一意」, unqualified
    zh-CN "岗位的唯一机器名称(例如 admin、editor、viewer)" 「唯一」, unqualified

    ⇒ Three of four shipped locales still tell an admin the position name is unique installation-wide, which the declared index no longer does. ⛔ en is out of scope and must not be touched — editing a correct leaf is a regression risk with no upside.

    ⛔ Also out of scope, per the card's own guards: the generator (#8543, another seat), the bundle structure, and the "sweep for other stale bundles" suggestion — that is a separate card if wanted, not a rider.


    Generated by Claude Code

  5. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor
    {
      "issue": 8601,
      "status": "done",
      "branch": "claude/issue-8601-sys-position-bundle-locales",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/8723",
      "premise_still_valid": true,
      "summary": "Your premise correction is confirmed independently: `Unique machine name for the position` returns zero on current main, and the zero is not vacuous (sys_position is present in en at :12). The en leaf at :22 already matches the source verbatim, so en was left untouched. The other three shipped locales were stale exactly as you measured, and their `sys_position.fields.name.help` leaves are now corrected: es-ES `Nombre tecnico del puesto, unico por organizacion (p. ej. sales_manager, hr_specialist).`, ja-JP `ポジションのマシン名(組織ごとに一意。例: sales_manager、hr_specialist)`, zh-CN `岗位的机器名称,在每个组织内唯一(例如 sales_manager、hr_specialist)`. Each is anchored to the idiom PR #8599 already landed IN THESE SAME FILES for sys_permission_set.fields.name.help (:188), so the locales stay internally consistent instead of inventing a fourth phrasing; ja-JP also moves the odd 機械名 to マシン名, the term the rest of that bundle uses. Diff is exactly 3 leaf values, no structural edit. TWO DIVERGENCES TO FLAG: (1) your dispatch-prompt table transcribed zh-CN as 唯一機械名称 (Japanese-style 機械); the real bytes are 唯一机器名称, which is what your GitHub claim comment says - the prompt table was the mistranscription, your claim comment was right. (2) sys_position has a SECOND leaf carrying this same defect, outside the file surface you pinned - filed as #8718, see below.",
      "tests": "All gates run at f11fb28, which is the final commit and the PR head sha (verified equal to the PR's head.sha). `pnpm check:i18n` OK - 9 packages, all bundles in sync, and its --self-test passes so the drift classifier can still go red. As the card predicts, this gate is green either way, so it is evidence of structural integrity ONLY, not of translation correctness. Note the gate first refused to run at all: 'PREREQUISITE NOT MET - the workspace CLI is not built' (it runs the built CLI); resolved with turbo build --filter=@objectstack/cli, 55 tasks successful. YOUR SECTION 3 QUESTION, ANSWERED: `node scripts/check-i18n-bundles.mjs --write` does NOT clobber the hand edits. It printed 'regenerated' for all nine packages and rewrote these three files byte-identically - `git status` came back completely clean against my commit. The sanctioned edit-in-place workflow is intact and #8543 is not worse than filed; the same merge-mode behaviour that let the drift survive is what makes hand-edited leaves safe. I committed the fix BEFORE running --write specifically so that test had a real restore point. Also green: check:cross-package-test-inputs, check:test-source-alias (72 pkgs), check:type-source-resolution (76 pkgs), check:changeset-gate-self-tests, check:objectui-changeset, check-cross-package-test-inputs.mjs, check-empty-changeset.mjs (1 declaring changeset), check-changeset-no-major.mjs, check-adr-0087-registration.mjs, check-nul-bytes.mjs (5745 files) plus a targeted grep -naP control-byte self-scan of the three edited files, clean. The last five were NOT in your gate list - they are changeset-triggered and your list predates this PR's changeset; surfaced by re-running scripts/pm/dispatch-gates.mjs against my actual changed paths, as the contract requires. NOT RUN: `pnpm --filter @objectstack/plugin-security test`. Three bounded flock attempts (~24 min queued total) all returned 99. Holder named: PID 1653, a sibling agent running `pnpm build --concurrency=2 && pnpm --workspace-concurrency=2 --no-bail --filter '...@objectstack/objectql' test` under a blind `flock -w 7200`, 20+ minutes in and still actively progressing (its child node PID 7979 alive at 17:12) - a live holder, not an abandoned lock. I stopped rather than idle-poll, per the report-at-draft-PR-time rule; CI runs this suite. The change is three string literals in a translation bundle with no new test coverage to add - its correctness is the translation judgement above, not a suite outcome.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #8718: sys_position's clone_position action param helpText - the SECOND leaf stating the same uniqueness rule - is still unqualified in es-ES (`Nombre de maquina snake_case unico`), ja-JP (`一意の snake_case マシン名`) and zh-CN (`唯一的 snake_case 机器名称`), while en :99 already reads `snake_case machine name, unique per organization` matching sys-position.object.ts:116 verbatim. Corrected at source by the SAME #8468 - its source comment at :112-114 says so explicitly ('the name must be free within THIS organization, not across'). Same defect, same object, same three files, one leaf over; it is the string an admin reads at the exact moment they type a new name. Left unfixed because your file surface pinned fields.name.help 'nothing else, stop on breach, explain in the report' - this is that breach report. It is a 3-line change in the files PR #8723 already touches if you would rather fold it in than dispatch it. Searched open issues first (keyword + file-path): no existing card.",
        "NOT filed, recorded here only - the es-ES bundle has broken-Spanish artifacts from what looks like a global rol->puesto find-replace: sys_position.pluralLabel is `Puestoes` (should be `Puestos`), its description reads `Definiciones de puesto para el contpuesto de acceso RBAC` (`control` was mangled into `contpuesto`), and clone_position.label still says `Clonar rol`. Tripped over while reading the exact lines this card needed - I did not sweep for more, since the card explicitly forbids the bundle sweep. Say the word and I will file it; it is cosmetic-but-shipped and reads as a separate es-ES quality card."
      ]
    }

    Generated by Claude Code


    Generated by Claude Code

  6. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor

    Patch round delta — supersedes the JSON in my previous comment. New head sha: 31aeb70.

    1. sys_position's clone-dialog helpText still asserts unqualified uniqueness in es-ES/ja-JP/zh-CN #8718 folded in. Three clone_position.params.name.helpText leaves corrected in es-ES / ja-JP / zh-CN. The anchor turned out to be exact rather than approximate: en is byte-identical at :99 and :277, so each locale's target was simply its own already-landed :277 string from PR fix(plugin-security,plugin-sharing,plugin-webhooks,platform-objects,service-messaging,spec): scope five tenant-scoped declared unique indexes per organization (#8554) #8599. No new phrasing was invented for any of the six strings now changed. Verified after editing — all four locales match at :99 and :277. PR body now carries Fixes #8601 and Fixes #8718, and states the fold-in was on PM instruction because a separate PR would touch the identical three files.
    2. es-ES quality card filed as es-ES object bundle carries rol→puesto find-replace damage (Puestoes, contpuesto, a surviving Clonar rol) #8735 — unassigned, no labels, duplicate-checked (two searches, zero hits). States plainly that it is a sample, not a bounded set, and that no sweep was done because sys_position's shipped en bundle still asserts installation-wide uniqueness that #8556 corrected at source #8601 forbade it; tells the next picker-up to bound it first. Linked to sys_position's shipped en bundle still asserts installation-wide uniqueness that #8556 corrected at source #8601 and check-i18n-bundles merge mode never updates an EXISTING field description, so editing one leaves the en bundle silently stale (and the gate green) #8543. Not touched in PR fix(plugin-security): say "unique per organization" in sys_position's es-ES/ja-JP/zh-CN help #8723.
    3. Test suite not retried, per your instruction.
    {
      "issue": 8601,
      "status": "done",
      "branch": "claude/issue-8601-sys-position-bundle-locales",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/8723",
      "head_sha": "31aeb70",
      "premise_still_valid": true,
      "summary": "Both leaves where sys_position states the machine-name uniqueness rule are now qualified per organization in es-ES, ja-JP and zh-CN: fields.name.help (also picking up the source's current sales_manager/hr_specialist examples) and actions.clone_position.params.name.helpText, folded in on PM instruction as a correction to the dispatch's file surface rather than a scope breach. en was already correct at both leaves and stays untouched. Six leaf values, three files, two commits, no structural edit; every target string was already accepted in these same files by PR #8599.",
      "tests": "All gates re-run at 31aeb70, after the final commit. check:i18n OK (9 packages in sync, --self-test passes) - green either way by design, so it evidences structural integrity only, not translation correctness. Also green at 31aeb70: check:cross-package-test-inputs, check:test-source-alias, check:type-source-resolution, check:changeset-gate-self-tests, check:objectui-changeset, check-cross-package-test-inputs.mjs, check-empty-changeset.mjs, check-changeset-no-major.mjs, check-adr-0087-registration.mjs, check-nul-bytes.mjs (5745 files), plus a targeted control-byte scan of the three edited files. Gate set re-derived with scripts/pm/dispatch-gates.mjs against the new diff - unchanged, because the changed paths are unchanged. The --write clobber test from the previous round still stands and was not re-run. pnpm --filter @objectstack/plugin-security test deliberately NOT retried per PM instruction; CI's conclusion is the reading that counts.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #8735: es-ES bundle find-replace damage (Puestoes / contpuesto / a surviving Clonar rol). Unassigned, no labels, duplicate-checked. Explicitly a sample, not a bounded set - no sweep was performed.",
        "#8718 is no longer out of scope - folded into PR #8723 on PM instruction and closed by it."
      ]
    }

    Generated by Claude Code


    Generated by Claude Code

  7. hotlong commented on Aug 14, 2026

    @hotlong
    Contributor

    ACCEPT — PR #8723 (head 31aeb70), with #8718 folded in.

    PM session session_01XeQRiAa7vYRVX5Fog7Zby8. Landing waits on gate conclusions.

    Six leaf values, three files, en untouched at both leaves. The PR carries Fixes #8601 and Fixes #8718.

    The part worth recording

    The fold-in anchor turned out to be exact rather than approximate. en is byte-identical at :99 and :277, so each locale's target for the clone-dialog leaf was its own already-landed string from PR #8599 — no new phrasing was invented for any of the six values, in any locale. That is the strongest available answer to a change whose gate cannot judge it: instead of three fresh translations, three locales were made self-consistent with strings this repo already accepted.

    Two corrections that went the right way

    • My premise was wrong and you confirmed it independently rather than inheriting it: the en leaf was already correct, so the card as filed was half-dead and en correctly stays untouched.
    • My dispatch-prompt table was wrong (I transcribed zh-CN with Japanese-style 機械; the real bytes are 机器). You read the file rather than my table. The prompt hedged that line for exactly this reason, but the mistranscription was still mine.

    On the gate that cannot judge this

    check:i18n is green either way — that is #8543 and it is why this drift survived. Your --write clobber test is the useful artifact: it rewrote all three files byte-identically with a clean git status, so the sanctioned edit-in-place workflow is intact and #8543 is not worse than filed. That answered the open question I attached to the dispatch.

    pnpm --filter @objectstack/plugin-security test remains not-run locally, by my instruction, after the shared verify lock was held throughout by a batch sibling. CI's conclusion for that suite is the reading I will take before this lands — a local green would not have been better evidence.

    Out-of-scope work, checked

    #8735 filed for the es-ES rol→puesto find-replace damage (Puestoes, contpuesto, a surviving Clonar rol) — unassigned, unlabelled, duplicate-checked twice, and correctly stating that it is a sample rather than a bounded set because #8601 forbade the sweep. That last sentence is what makes it safe to pick up; a card that implies it is exhaustive when it is not is how a "fix" ships half a problem.

    ⛔ Not folded in, and right not to be: it is a different defect class from the uniqueness claim and wants an es-ES review of its own.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions