Repository navigation
main is RED: console.ai.pendingDrafts exists only in en and zh — the eight other locale packs have no such block at all, so all-locales-key-parity fails on main and on every PR that touches source #5705
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Aug 22, 2026 Claim —
domain:uiexecution seat.- Session:
session_012u2pRjcqAYtoEjgr3wwhnK - Branch:
claude/issue-5705-pending-drafts-locale-parity - Seat post: [PM seat] domain:ui @ objectui — 🟢 os-steve · session_016djJF12Qt14ejKR5Vjt4sK · batch 3 · 18 landed · round 8 in flight #5560
Dispatching immediately. This is not a new round's card — it is the blocker that stops round 16's own remaining PRs (#5699, and the two still in flight for #5235 / #5279, all of which touch source and therefore get a real shard run) from landing on a green base. Clearing it is part of finishing the work already in flight.
Scope is the eight packs, five keys, matching
en.ts:1690-1696.⚠️ countandpublishedWithFindingscarry interpolations ({{count}},{{detail}}) that must survive translation.
Generated by Claude Code
- Session:
CI corroborates the parse — independently, and against the grep.
#5706 (a different card,
packages/authonly) has now hit this onTest (shard 2/4). Its annotations, read from the check-run API:annotations : 9 paths : ['.github', 'packages/i18n/src/__tests__/all-locales-key-parity.test.ts'] locales : ['ar','de','es','fr','ja','ko','pt','ru'] keys : ['console.ai.pendingDrafts.count', '…failed', '…publish', '…published', '…publishedWithFindings'] NON-parity annotations: NONETwo things this settles:
-
All eight locales are missing all five keys — not four packs partially fixed. That matches the block-level parse in the card and contradicts the occurrence count that reported
2forpt/es/fr/de. CI is an independent instrument and it agrees with the parse, so the grep reading is confirmed wrong rather than merely suspect. Anyone re-checking this: parse the blocks. -
The failure carries nothing else. No annotation outside the parity test, so a PR inheriting this is inheriting exactly one defect, not a cluster. That is what makes it safe to hold the affected PRs unchanged rather than rebase or patch them — there is nothing else in the base for them to absorb.
Three PRs are now held on this: #5699, #5706, #5707. None of them needs to change; all three merge when the base is green.
Generated by Claude Code
-
- added a commit that references this issue
on Aug 22, 2026 { "issue": 5705, "status": "done", "branch": "claude/issue-5705-pending-drafts-locale-parity", "pr": "https://github.com/objectstack-ai/objectui/pull/5708", "premise_still_valid": true, "summary": "Added the five console.ai.pendingDrafts keys (count, publish, published, failed, publishedWithFindings), translated, to the eight packs that had no such block: ar, ru, pt, es, fr, de, ko, ja. Placed at en's position (first key inside console.ai, immediately before usage), anchored on the parsed ` ai: {` line rather than a grep for `pendingDrafts` — the card's measurement trap, since two unrelated blocks carry that name. Each pack keeps its own conventions rather than en's: all eight quote with double quotes, ru puts the number last (`...: {{count}}`) as it already does for the sibling home.pendingDrafts counts, and ja uses the full-width colon before {{detail}} per that pack's documented rule (full-width when the interpolation carries a message, half-width for a single token); both deviations carry a short in-pack note in the pack's own language. Terminology was lifted from each pack's existing publish-bar vocabulary (home.pendingDrafts, console.ai.seedWarn, console.ai.publishFailed). Diff is 60 insertions, 0 deletions, 8 locale files plus a changeset — no reordering, no other parity gaps touched.", "tests": "All results at final commit 739dd78b6 (verification union re-run after the last commit, on a clean tree). RED LEG captured before the fix on origin/main 83ec61881: `pnpm exec vitest run packages/i18n/src/__tests__/all-locales-key-parity.test.ts` -> 'Test Files 1 failed (1) / Tests 8 failed | 24 passed (32)', each failure 'AssertionError: %s is missing 5 key(s)' listing exactly console.ai.pendingDrafts.{count,failed,publish,published,publishedWithFindings} for ja/ko/de/fr/es/pt/ru/ar. GREEN LEG same file with --reporter=verbose: 'Test Files 1 passed (1) / Tests 32 passed (32)', naming all nine '%s defines every en key' AND all nine of the sibling '%s defines no key that en lacks' (the other-direction assertion), plus 'placeholders match en in every pack' and both non-vacuity guards. Exactly the 8 cases flipped red->green. PLACEHOLDERS verified mechanically against the EVALUATED packs via tsx (not a text grep): all ten packs report keys=5, {{count}} present in count, {{detail}} present in publishedWithFindings, per-key placeholder shape equal to en's, and the unrelated home.pendingDrafts block still holding message/cta and gaining nothing -> 'VERIFY OK — 0 failures'. SCOPED SUITE (verify-lock scope = the edited package plus the one provable consumer, packages/app-shell/src/console/ai/PendingDraftsBar.tsx, established by grepping every call site of console.ai.pendingDrafts — it is the only one; NOT app-shell's full 493-file suite): `pnpm exec vitest run --maxWorkers=2 packages/i18n/ packages/app-shell/src/console/ai/__tests__/PendingDraftsBar.test.tsx` -> 'Test Files 52 passed (52) / Tests 883 passed (883)'. GATES, each read from its own printed verdict line, exit code captured before any pipe: check-i18n-en-drift.mjs RC=0 (no en value changed); check-i18n-call-site-keys.mjs RC=0; check-i18n-dead-keys.mjs RC=0 (a report, not a gate, per its own header); check-control-bytes.mjs 'OK (scanned 4756 tracked text file(s); skipped 85 binary)'; `pnpm --filter @object-ui/i18n type-check` exit 0 with the script name echoed as 'tsc --noEmit && tsc -p tsconfig.test.json' (so not a zero-match no-op — note objectui spells it type-check, hyphenated); `pnpm --filter @object-ui/i18n lint` '34 problems (0 errors, 34 warnings)', all pre-existing and none in a locale file. LINT NARROWING stated as a measurement: eslint --no-inline-config --format json over the diff = 8 files, 0 errors, 0 warnings; the full population eslint itself resolves is 3544 files and that run also reports 0 findings in any packages/i18n/src/locales/ file; the config sets no projectService/project:, so linting is not type-aware and this diff cannot move any untouched file's verdict. All heavy runs went through the shared verify lock (scripts/pm/os-verify-lock.sh); every VERDICT line read command-exit 0 except the deliberate red leg.", "open_questions": [ { "question": "Already raised on the card, restated here because it is the reason this survived several merges and is a CI-topology call the maintainer owns: should all-locales-key-parity run in a cheap, unskippable job instead of only inside the shard that a source-free diff skips? Today the guard is real but is bypassed by exactly the PRs that are cheapest to merge (#5698, markdown-only, completed shard 1/4 in 13s — a skip, not a run), so parity debt accumulates between source-touching PRs rather than failing at the commit that creates it. This is the second en-only landing in one day.", "options": [ "A — Move the i18n parity/drift tests into a small always-run job (they cost ~4s for the parity file, ~22s for the whole i18n package), independent of the source-diff skip logic.", "B — Widen ci.yml's source-diff detector so packages/i18n/src/locales/** always counts as source, leaving the shard topology alone.", "C — Leave as is and rely on the follow-up discipline that has now under-delivered twice (#5696 en-only, #5697 zh-only)." ], "recommendation": "A, because the parity assertion is pack-intrinsic and cheap — it needs no build and no call site — so pinning it to the expensive shard buys nothing and costs exactly the coverage that matters. B fixes only the locale-file case; the same hole reopens the next time an en-only feature lands from a non-i18n directory, which is precisely how #5696 created this. Not implemented here: it is a CI-topology change and this card is a main-is-RED blocker that three round-16 PRs are held on, so it was kept minimal." } ], "out_of_scope_findings": [] }
Generated by Claude Code
Fix is up as #5708 and verified. Escalating the topology question behind it — that part is a maintainer call, not this seat's.
#5708 carries the eight packs plus a changeset,
+87/-0, no deletions and no reordering. Evidence I checked rather than took on trust:- Red leg captured first, on
origin/main83ec61881:Tests 8 failed | 24 passed (32), each failure naming exactly the fiveconsole.ai.pendingDrafts.*keys forja/ko/de/fr/es/pt/ru/ar. Green leg:32 passed, including all nine of the other-direction assertions (%s defines no key that en lacks) and both non-vacuity guards. Exactly the 8 cases flipped. - The two-blocks trap was avoided by construction — insertion anchored on the parsed
ai: {line, not on apendingDraftsgrep. - Placeholders verified against the evaluated packs (via
tsx, not a text scan): all ten packs report 5 keys,{{count}}incount,{{detail}}inpublishedWithFindings, per-key placeholder shape equal toen's — and the unrelatedhome.pendingDraftsblock still holdingmessage/ctaand gaining nothing. That last assertion is the one that proves the fix landed in the right block. - Per-pack conventions kept rather than
en's imposed:ruputs the number last, as it already does for the siblinghome.pendingDraftscounts;jauses the full-width colon before{{detail}}per that pack's documented rule. Both deviations carry an in-pack note in the pack's own language. - Verify-lock scoped to a provable superset —
packages/i18nplus the one consumer (PendingDraftsBar.tsx), established by enumerating every call site ofconsole.ai.pendingDrafts— not app-shell's 493-file fallback. 52 files / 883 tests.
The question I am not answering
Should
all-locales-key-parityrun in a cheap, unskippable job rather than only inside a shard that a source-free diff skips?The concrete measurement: #5698 was markdown-only and its
Test (shard 1/4)completed in 13 seconds — a skip, not a run. So it merged cleanly over amainthat was already red on this. Docs-only PRs sail past; the first source-touching PR eats it. Parity debt accumulates between source-touching PRs instead of failing at the commit that creates it.This is the second en-only landing in one day (#5696
en-only, then #5697 deliveringzhonly), which is why it is worth deciding rather than absorbing.Options as the implementing agent framed them, with its recommendation:
- A — move the i18n parity/drift tests into a small always-run job, independent of the source-diff skip logic. ~4s for the parity file, ~22s for the whole i18n package. (Recommended: the assertion is pack-intrinsic — no build, no call site — so pinning it to the expensive shard buys nothing and costs exactly the coverage that matters.)
- B — widen
ci.yml's source-diff detector sopackages/i18n/src/locales/**always counts as source. Smaller, but fixes only the locale-file case; the hole reopens the next time anen-only feature lands from a non-i18n directory, which is precisely how feat(app-shell): standing unpublished-changes bar on the AI build surface #5696 created this. - C — leave it, relying on follow-up discipline that has now under-delivered twice.
Deliberately not implemented in #5708: it is a CI-topology change, and this card is a
main-is-red blocker with three PRs held on it. Keeping the unblock minimal was the right call; the topology fix wants its own card and its own evidence.
Generated by Claude Code
- Red leg captured first, on
- added a commit that references this issue
on Aug 23, 2026
Filed by the
domain:uiexecution seat (seat post #5560). Found while landing #5699; that PR is held on this, not on its own diff.The breakage
packages/i18n/src/__tests__/all-locales-key-parity.test.tsfails onmain. Measured onorigin/main(83ec61881) by parsing each locale pack'spendingDrafts: {blocks and comparing immediate child keys againsten— not by grepping, for a reason given below:Eight packs × five keys. The parity test carries no allowlist —
expect(missing).toEqual([])— and has its own non-vacuity guard (EN.size > 2000,OTHER_LOCALESlength 9), so it cannot be passing vacuously.How it got here — and why the follow-up did not fix it
8e32da7d8(11:17:36Z, feat(app-shell): standing unpublished-changes bar on the AI build surface #5696) added the standing unpublished-changes bar withenkeys only. CI on that head: failure.c5200f041(11:50:27Z, fix(i18n,app-shell): pending-drafts bar keys land in the locale packs (#5696 follow-up, main is red) #5697) is titled "fix(i18n,app-shell): pending-drafts bar keys land in the locale packs (feat(app-shell): standing unpublished-changes bar on the AI build surface #5696 follow-up)". It landed them inzhonly. CI on that head: failure.So the follow-up that exists specifically to close this gap closed one ninth of it, and
mainhas been red across both.My first pass counted occurrences of the string
pendingDraftsper file and got 2 foren/zh/pt/es/fr/deand 1 forar/ru/ko/ja— which reads as "four packs were fixed, four were not". That is false. There are two unrelatedpendingDraftsblocks in these files: the newconsole.ai.pendingDrafts(en.ts:1690) and a pre-existing, different one (en.ts:2611, keysmessage/cta). The extra occurrence inpt/es/fr/deis not a second block — parsing finds exactly onependingDrafts: {in each of the eight. Anyone re-checking this by grep will get the wrong answer; parse the blocks.Blast radius — narrower than it looks, and that is the trap
This does not turn every PR red, which is why it has survived several merges unnoticed:
ci.ymlskips the expensive steps for a diff that touches no source. docs(plugin-form): state the field-level className rule as contract, not reader count #5698 (markdown-only) went green withTest (shard 1/4)completing in 13 seconds — a skip, not a run — and merged at 11:59Z.ADR-0057 D10as the framework's numbering at seven live citation sites #5699 touches.ts/.tsx, so it gets a real run, reaches this test, and goes red onTest (shard 2/4).So: docs-only PRs sail through; the first PR that touches source eats it. On
mainthe same failure shows up asTest (coverage shard 2/4).⛔
check_suite.completeddid not catch this, and could not haveEvery
check_suite.completedwebhook on #5699's head8faa2fea0reportedconclusion: successwhileTest (shard 2/4)andTest (shard 3/4)were stillin_progress— the suites that completed were the other ones. Reading those events as a green light would have landed this PR onto a red base ten minutes before the failure arrived. Gates must be read by name, per #4986.What a fix has to do
Add
console.ai.pendingDrafts—count,publish,published,failed,publishedWithFindings— to the eight remaining packs, matchingen.ts:1690-1696.countandpublishedWithFindingscarry interpolations ({{count}},{{detail}}) that must survive translation.Worth deciding at the same time, because this is the second time in a day that a feature landed
en-only and a follow-up under-delivered: whether the parity test should run in a cheap, unskippable job rather than only inside the shard that a source-free diff skips. As it stands the guard is real but is bypassed by exactly the PRs that are cheapest to merge, so the debt accumulates between source-touching PRs instead of being caught at the commit that creates it.Adjacent and separately known:
mainis also red onBuild Docs(#5668) and onTest (coverage)(#5402, failing 100% since 2026-08-16). This card is only the parity failure.