You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(plugin-detail): record:alert's CTA action.label is the third narrow slot in the same local props type — renderer resolves an inline locale map, the type says string #4998
Triage first-touch — concentrated round #2 (triage seat, session session_019ZyCHcjXeTFPiS8RWRk4nN, 2026-08-19): promoted finding → pm:queue · Task. Two-line fix (label?: string | I18nLabel in both copies of the local RecordAlertProps CTA slot), aligning the declaration with what the renderer already does (pickLocalized) — the same move #4970 landed for title/body in the same interface. The publish-surface half (declaring the member shape in the manifest) stays out of scope pending the ComponentInput member-shape question (#3795), exactly as the body reasons. Size/model suggestion: S-mechanical, sonnet.
Claim: PM loop round 3 (batch raised to 5 at the maintainer's instruction — 「任务很多,并发保持5」)
Session: session_012u2pRjcqAYtoEjgr3wwhnK
Branch: claude/issue-4998-record-alert-label-i18n
Worktree: objectui-issue-4998
Domain: domain:ui
File surface: packages/plugin-detail/src/renderers/record-alert.tsx and the second copy of the local RecordAlertProps CTA slot wherever it lives in packages/plugin-detail/** (+ tests, + a changeset) (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: sonnet — the floor, and this is the card that earns it: triage measured it as S-mechanical with a landed precedent (#4970 made the identical move for title/body in the same interface), the change is a type widening the renderer's runtime behaviour already implements, and correctness is decided by type-check rather than by judgment. The one search task — finding both copies, not one — is bounded and gate-checked.
Clause-②: no — widening a local props type to match what the renderer already does aligns a declaration with existing behaviour; it neither changes the accepted set nor widens the published surface. ⚠️ The publish-surface half (declaring the member shape in the manifest) is deliberately out of scope, parked on the ComponentInput member-shape question in #3795 — do not pull it in.
Serial constraints cleared: none — packages/plugin-detail/** has no in-flight claim in this lane and no PR this session touched it. Disjoint from round 3's other four (apps/console/**, packages/app-shell/src/views/studio-design/**, packages/components/src/renderers/layout/grid.tsx, packages/core/**).
Located on origin/main this round: packages/plugin-detail/src/renderers/record-alert.tsx with __tests__/record-alert.test.tsx and __tests__/record-alert.visibleWhen.evidence.test.tsx beside it.
os-dev-report
{
"issue": 4998,
"status": "done",
"branch": "claude/issue-4998-record-alert-label-i18n",
"pr": "#5572",
"premise_still_valid": true,
"summary": "Widened the local, unexported RecordAlertProps CTA slot's action.label from string to string | I18nLabel in both copies in packages/plugin-detail/src/renderers/record-alert.tsx (schema.properties.action.label line 98, flat-compat schema.action.label line 108), matching the pickLocalized(props.action?.label, language) resolution the renderer already performs at runtime. This is the same move #4970 landed for title/body in the same interface. Added a test asserting the case the type previously refused (a locale-map action.label rendering the resolved string via a real I18nProvider); the publish-surface manifest half stays out of scope per the ruling, parked on #3795.",
"tests": "All at commit dc14b64. pnpm --filter @object-ui/plugin-detail type-check: exit 0 (tsc --noEmit && tsc -p tsconfig.test.json, 0 errors). pnpm exec vitest run packages/plugin-detail/src/renderers/tests/record-alert.test.tsx: 21/21 passed (1 test file). pnpm exec vitest run packages/plugin-detail/: 90 test files / 848 tests passed. pnpm --filter @object-ui/plugin-detail lint: exit 0, 0 errors (809 pre-existing no-explicit-any/react-hooks warnings, none on touched lines, confirmed by grep against changed files). node scripts/check-control-bytes.mjs: OK, 4629 tracked text files scanned. node scripts/check-changeset-presence.mjs: 2 source files changed under src/, 1 changeset declared -> pass. node scripts/check-changeset-no-major.mjs: pass, no major bump. node scripts/check-changeset-fixed.mjs: pass, all workspace packages in fixed group. Reverse verification: reverted only the type declaration in record-alert.tsx to the pre-fix label?: string (source-only, confirmed on disk via grep), reran type-check -> exit 2, tsc reported TS2322 at exactly the new test's locale-map literal (record-alert.test.tsx:219:17, "Type '{ en: string; zh-CN: string; }' is not assignable to type 'string'"); the pre-existing plain-string CTA test stayed unaffected. Restored the fix via git checkout from the committed branch state (git status clean afterward), reran type-check -> exit 0 again. This confirms the new locale-map test -- not the pre-existing plain-string CTA test -- is the case the narrow declaration refused.",
"open_questions": [],
"out_of_scope_findings": []
}
PM · review of PR #5572 — the ablation is the right one for a type-level fix
Most reverse verifications this session mutated behaviour and watched tests go red. That would have proved nothing here, because the renderer already resolved locale maps at runtime — pickLocalized takes unknown, so every vitest assertion is green with the narrow declaration too. You ablated the thing that actually carries the fix:
reverted only the type declaration to label?: string (source-only, confirmed on disk via grep), reran type-check → exit 2, TS2322 at exactly the new test's locale-map literal (record-alert.test.tsx:219:17, "Type '{ en: string; zh-CN: string; }' is not assignable to type 'string'"); the pre-existing plain-string CTA test stayed unaffected. Restored, re-ran → exit 0.
That establishes two separate things, and the second is the one reviewers usually skip: not just that the pin fails without the fix, but which test carries the discrimination — the new locale-map case, not the plain-string case sitting three lines above it. I had flagged exactly this doubt on my own read before your report arrived; you had already closed it.
Checked independently, not taken from the report
Both copies widened — schema.properties.action.label (:98) and the flat compat mirror schema.action.label (:108). Finding one and shipping was this card's failure mode; triage said "both copies" for that reason.
The stale docblock was rewritten, not left to rot. It previously read "deliberately NOT widened here (objectui#4998)" — a sentence that would have become false the moment this merged. It now states the widening, why (pickLocalized parity with title/body), and that it is type-only.
The out-of-scope half stayed out. The published surface still declares action as a bare object with the member shape in prose, so there is no manifest arm to align; parked on fix(plugin-detail): record:highlights 的 fields 声明补上 readonly,让 manifest 能被作者读到 (#3407) #3795 and said so in both the code comment and the changeset, which is where a future reader will actually look.
Unprompted care worth naming: wrapping the new case in a real I18nProvider pinned to en so it does not ride whatever language another test file left on the global i18next singleton. Nothing asked for that; a locale test that silently depends on file execution order is a flake waiting for a busy CI runner.
This was dispatched at the sonnet floor — triage measured it S-mechanical with a landed precedent (#4970) and correctness decided by type-check rather than judgment. That call holds: the floor was the right tier, and the work came back with a better ablation than the tier required.
Status
Path surface (get_files): 3 files, all packages/plugin-detail/** plus the changeset. No governed surface → ordinary ready → merge-queue path.
CI on #5572: Build & E2E, Build Docs and all three changeset gates green; the four Test shards and Type Check still in_progress, nothing red. Type Check is the gate that decides this card, so no verdict and no enqueue until it reads completed: success by name.
CI converged. Read by name: Type Check (the gate that decides this card), Test (shard 1/4)(2/4)(3/4)(4/4), Lint, Build & E2E, Bundle Analysis, Control Byte Scan, all three changeset gates, both doc type checks, Internal Docs Link Check, Skill Guide Path Check, Build Docs, Live E2E → every one completed: success. 19 success / 3 skipped / 0 failures / 0 in progress.
Path surface (get_files): 3 files, all packages/plugin-detail/** plus the changeset. No governed surface → ordinary ready → merge-queue path.
Substantive review is in the comment above and does not depend on this run.
Incidental corroboration of the "type-only" claim: plugin-detail reads 60.89 KB gzipped in Bundle Analysis — byte-identical to the pre-change figure, which is exactly what a type widening should produce.
Activity
docs(plugin-detail): name the CTA label slot this pass deliberately l…
os-support-ai commentedon Aug 19, 2026
Triage first-touch — concentrated round #2 (triage seat, session
session_019ZyCHcjXeTFPiS8RWRk4nN, 2026-08-19): promotedfinding→pm:queue· Task. Two-line fix (label?: string | I18nLabelin both copies of the localRecordAlertPropsCTA slot), aligning the declaration with what the renderer already does (pickLocalized) — the same move #4970 landed fortitle/bodyin the same interface. The publish-surface half (declaring the member shape in the manifest) stays out of scope pending theComponentInputmember-shape question (#3795), exactly as the body reasons. Size/model suggestion: S-mechanical, sonnet.Generated by Claude Code
os-sales commentedon Aug 21, 2026
Claim: PM loop round 3 (batch raised to 5 at the maintainer's instruction — 「任务很多,并发保持5」)⚠️ The publish-surface half (declaring the member shape in the manifest) is deliberately out of scope, parked on the
Session:
session_012u2pRjcqAYtoEjgr3wwhnKBranch:
claude/issue-4998-record-alert-label-i18nWorktree:
objectui-issue-4998Domain:
domain:uiFile surface:
packages/plugin-detail/src/renderers/record-alert.tsxand the second copy of the localRecordAlertPropsCTA slot wherever it lives inpackages/plugin-detail/**(+ tests, + a changeset) (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: sonnet— the floor, and this is the card that earns it: triage measured it as S-mechanical with a landed precedent (#4970 made the identical move fortitle/bodyin the same interface), the change is a type widening the renderer's runtime behaviour already implements, and correctness is decided bytype-checkrather than by judgment. The one search task — finding both copies, not one — is bounded and gate-checked.Clause-②: no — widening a local props type to match what the renderer already does aligns a declaration with existing behaviour; it neither changes the accepted set nor widens the published surface.
ComponentInputmember-shape question in #3795 — do not pull it in.Serial constraints cleared: none —
packages/plugin-detail/**has no in-flight claim in this lane and no PR this session touched it. Disjoint from round 3's other four (apps/console/**,packages/app-shell/src/views/studio-design/**,packages/components/src/renderers/layout/grid.tsx,packages/core/**).Located on
origin/mainthis round:packages/plugin-detail/src/renderers/record-alert.tsxwith__tests__/record-alert.test.tsxand__tests__/record-alert.visibleWhen.evidence.test.tsxbeside it.Generated by Claude Code
fix(plugin-detail): record:alert CTA action.label accepts the inline …
os-sales commentedon Aug 21, 2026
os-dev-report
{
"issue": 4998,
"status": "done",
"branch": "claude/issue-4998-record-alert-label-i18n",
"pr": "#5572",
"premise_still_valid": true,
"summary": "Widened the local, unexported RecordAlertProps CTA slot's action.label from string to string | I18nLabel in both copies in packages/plugin-detail/src/renderers/record-alert.tsx (schema.properties.action.label line 98, flat-compat schema.action.label line 108), matching the pickLocalized(props.action?.label, language) resolution the renderer already performs at runtime. This is the same move #4970 landed for title/body in the same interface. Added a test asserting the case the type previously refused (a locale-map action.label rendering the resolved string via a real I18nProvider); the publish-surface manifest half stays out of scope per the ruling, parked on #3795.",
"tests": "All at commit dc14b64. pnpm --filter @object-ui/plugin-detail type-check: exit 0 (tsc --noEmit && tsc -p tsconfig.test.json, 0 errors). pnpm exec vitest run packages/plugin-detail/src/renderers/tests/record-alert.test.tsx: 21/21 passed (1 test file). pnpm exec vitest run packages/plugin-detail/: 90 test files / 848 tests passed. pnpm --filter @object-ui/plugin-detail lint: exit 0, 0 errors (809 pre-existing no-explicit-any/react-hooks warnings, none on touched lines, confirmed by grep against changed files). node scripts/check-control-bytes.mjs: OK, 4629 tracked text files scanned. node scripts/check-changeset-presence.mjs: 2 source files changed under src/, 1 changeset declared -> pass. node scripts/check-changeset-no-major.mjs: pass, no major bump. node scripts/check-changeset-fixed.mjs: pass, all workspace packages in fixed group. Reverse verification: reverted only the type declaration in record-alert.tsx to the pre-fix label?: string (source-only, confirmed on disk via grep), reran type-check -> exit 2, tsc reported TS2322 at exactly the new test's locale-map literal (record-alert.test.tsx:219:17, "Type '{ en: string; zh-CN: string; }' is not assignable to type 'string'"); the pre-existing plain-string CTA test stayed unaffected. Restored the fix via git checkout from the committed branch state (git status clean afterward), reran type-check -> exit 0 again. This confirms the new locale-map test -- not the pre-existing plain-string CTA test -- is the case the narrow declaration refused.",
"open_questions": [],
"out_of_scope_findings": []
}
Generated by Claude Code
os-sales commentedon Aug 21, 2026
PM · review of PR #5572 — the ablation is the right one for a type-level fix
Most reverse verifications this session mutated behaviour and watched tests go red. That would have proved nothing here, because the renderer already resolved locale maps at runtime —
pickLocalizedtakesunknown, so every vitest assertion is green with the narrow declaration too. You ablated the thing that actually carries the fix:That establishes two separate things, and the second is the one reviewers usually skip: not just that the pin fails without the fix, but which test carries the discrimination — the new locale-map case, not the plain-string case sitting three lines above it. I had flagged exactly this doubt on my own read before your report arrived; you had already closed it.
Checked independently, not taken from the report
schema.properties.action.label(:98) and the flat compat mirrorschema.action.label(:108). Finding one and shipping was this card's failure mode; triage said "both copies" for that reason.pickLocalizedparity withtitle/body), and that it is type-only.actionas a bareobjectwith the member shape in prose, so there is no manifest arm to align; parked on fix(plugin-detail): record:highlights 的 fields 声明补上 readonly,让 manifest 能被作者读到 (#3407) #3795 and said so in both the code comment and the changeset, which is where a future reader will actually look.I18nProviderpinned toenso it does not ride whatever language another test file left on the global i18next singleton. Nothing asked for that; a locale test that silently depends on file execution order is a flake waiting for a busy CI runner.This was dispatched at the sonnet floor — triage measured it S-mechanical with a landed precedent (#4970) and correctness decided by
type-checkrather than judgment. That call holds: the floor was the right tier, and the work came back with a better ablation than the tier required.Status
Path surface (
get_files): 3 files, allpackages/plugin-detail/**plus the changeset. No governed surface → ordinary ready → merge-queue path.CI on #5572:
Build & E2E,Build Docsand all three changeset gates green; the fourTestshards andType Checkstillin_progress, nothing red.Type Checkis the gate that decides this card, so no verdict and no enqueue until it readscompleted: successby name.Generated by Claude Code
os-sales commentedon Aug 21, 2026
ACCEPT — PR #5572
CI converged. Read by name:
Type Check(the gate that decides this card),Test (shard 1/4)(2/4)(3/4)(4/4),Lint,Build & E2E,Bundle Analysis,Control Byte Scan, all three changeset gates, both doc type checks,Internal Docs Link Check,Skill Guide Path Check,Build Docs,Live E2E→ every onecompleted: success. 19 success / 3 skipped / 0 failures / 0 in progress.Path surface (
get_files): 3 files, allpackages/plugin-detail/**plus the changeset. No governed surface → ordinary ready → merge-queue path.Substantive review is in the comment above and does not depend on this run.
Incidental corroboration of the "type-only" claim:
plugin-detailreads 60.89 KB gzipped in Bundle Analysis — byte-identical to the pre-change figure, which is exactly what a type widening should produce.Driving to landing.
Generated by Claude Code
fix(components,plugin-detail): element:text.content / element:button.…
fix(plugin-detail): record:alert CTA action.label accepts the inline …
fix(plugin-detail): record:alert resolves its CTA through resolveDecl…