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.
The page-editor palette offers the legacy record:chatter and (as of the 17.1.0 pin) explicitly excludes the canonical record:discussion — the pair is advertised under the alias #5495
Observation filed unassigned by the dev seat implementing the @objectstack/spec 17.1.0 pin bump (#5328). Not a defect that breaks anything today — the palette works — but the naming is inverted and someone should decide which way it points.
What was measured
record:chatter and record:discussion are the same renderer under two names — packages/plugin-detail/src/index.tsx:589 says so directly, and packages/core/src/registry/public-blocks.ts:57 records the direction:
record:chatter … as record:discussion under a Salesforce-familiar name, kept for schemas
So record:discussion is the canonical spelling and record:chatter is the compatibility alias. objectui has emitted the canonical one all along — packages/plugin-detail/src/synth/buildDefaultPageSchema.ts:731 is componentNode('record:discussion').
The metadata-admin palette, however, offers record:chatter (BLOCK_TYPE_META, labelled "Chatter feed") and had no entry for record:discussion at all, because spec 17.0.0's PageComponentType did not declare the canonical name. 17.1.0 added it (34 members before and after — element:filter left as record:discussion arrived, so the member count is unchanged and hides the swap).
That made block-config.test.ts's "every spec block type is either offered or explicitly excluded" fail on the pin bump, and #5328 resolved it the no-UX-change way: a PALETTE_EXCLUSIONS entry for record:discussion reading "same renderer as the offered record:chatter — one palette entry per renderer".
Why that resolution deserves a follow-up
It is correct as a pin-bump edit — offering both would put two identical blocks in the palette, and flipping which one is offered changes what authors drag — but it leaves the tree in a slightly odd state: the palette now explicitly excludes the canonical name and advertises the alias.
The decision
Either:
offer record:discussion, exclude record:chatter — palette matches the canonical spec name and the schema objectui itself emits; the alias stays renderable for existing schemas, just not advertised. Author-visible label probably stays "Discussion". Changes what new pages get authored with, which is the point.
keep it as is and record that "Chatter feed" is the deliberate author-facing name for the pair, in which case the exclusion comment is the whole story and this card closes as won't-fix.
Refs: #5328 (where it surfaced) · #4935 (the sibling element:filter residue in the same file).
Triage (first-touch): routed to the decision inbox (needs-user-decision, domain:ui, type Task). The palette currently advertises the compatibility alias and explicitly excludes the canonical name — which way it points changes what authors see and what new pages get authored with, an author-facing naming call on the manual floor (small, one-letter answer). Chinese four-facet analysis below.
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat, session_01ApyDuQY2fkunMCqXiqvBhR)
The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Option A — the palette offers the canonical name. record:discussion is offered in the page-editor palette and record:chatter becomes the explicitly excluded compatibility alias, inverting the current PALETTE_EXCLUSIONS state. The author-facing label changes from "Chatter feed" to "Discussion"; the alias stays renderable for existing schemas, just no longer advertised. Per the triage execution note this is an S-size card: BLOCK_TYPE_META rename, PALETTE_EXCLUSIONS inversion, the block-config.test.ts assertion following along, and a check of the #4935 sibling element:filter residue in the same file.
State: needs-user-decision removed → pm:queue (ready for dispatch).
Executing the 2026-08-22 maintainer ruling: Option A — the palette offers the canonical name.record:discussion is offered; record:chatter becomes the explicitly excluded compatibility alias, inverting the current PALETTE_EXCLUSIONS state. The label moves "Chatter feed" → "Discussion". ⛔ The alias stays renderable for existing schemas — this changes what is advertised, not what works.
S-size scope as the triage execution note records it: BLOCK_TYPE_META rename · PALETTE_EXCLUSIONS inversion · the block-config.test.ts assertion following along · and a check of the #4935 sibling element:filter residue in the same file.
⚠️ On that last item, read #4935's 2026-08-22 unlock comment before touching it: residue 1 no longer exists — PALETTE_EXCLUSIONS['element:filter'] was already deleted by #5529, which had to touch this same file once the enum member disappeared. So the check is to confirm that and report what (if anything) is left, ⛔ not to re-delete something already gone.
Hot-file serialisation: #4935 is held behind this card — both land in packages/app-shell/src/views/metadata-admin/previews/block-types.ts.
{
"issue": 5495,
"status": "done",
"branch": "claude/issue-5495-palette-canonical-discussion",
"pr": "https://github.com/objectstack-ai/objectui/pull/5838",
"premise_still_valid": true,
"summary": "Executed the 2026-08-22 maintainer ruling (Option A) in packages/app-shell/src/views/metadata-admin/previews/block-types.ts: BLOCK_TYPE_META now offers the canonical 'record:discussion' labelled \"Discussion\" (was 'record:chatter' / \"Chatter feed\"), and PALETTE_EXCLUSIONS now excludes 'record:chatter' as the compatibility alias — inverting the pair. Icon and category are unchanged. The alias stays fully renderable: nothing in plugin-detail was touched, and a new test (previews/__tests__/palette-discussion-alias.test.tsx) pins that the registry still resolves 'record:chatter' to the SAME renderer function object as the canonical name and that an alias schema still renders the discussion panel — so 'no longer offered' cannot drift into 'no longer rendered'. block-config.test.ts needed no edit and that is the point: it derives palette coverage from PageComponentType and is satisfied by either direction of this pair, which is why the direction now has a test of its own. Scope item 4 confirmed without acting: 'element:filter' has zero hits in block-types.ts on current main — #5529 already deleted PALETTE_EXCLUSIONS['element:filter'], exactly as #4935's 2026-08-22 unlock comment records; nothing re-deleted, #4935's remaining elements.tsx residue left alone. Changeset added (minor, @object-ui/app-shell) declaring the label change, the offered-block change, and the one knock-on below.",
"tests": "All from repo root; gate union re-run on the FINAL commit 85c289455 with a clean tree. (1) SPEC PIN, counter-probed before relying on it — resolved @objectstack/spec = 17.2.0, PageComponentType.options = 34 members; 'record:discussion' -> true, 'record:chatter' -> true, 'record:details' -> true (known-present), 'element:filter' -> false (genuinely retired), 'zzNotARealType' -> false (never existed). Two trues and two falses from one probe, so a broken probe cannot read as passing. (2) TESTS: `pnpm exec vitest run <palette-discussion-alias.test.tsx> <block-config.test.ts>` -> 'Test Files 2 passed (2) / Tests 35 passed (35)', exit 0. Broader: `pnpm exec vitest run packages/app-shell/src/views/metadata-admin/previews apps/console/src/__tests__/public-contract.test.ts packages/app-shell/src/utils/__tests__/pageSchemaIntrospect.test.ts` -> 'Test Files 40 passed (40) / Tests 481 passed (481)', exit 0. (3) TYPECHECK: `pnpm --filter @object-ui/app-shell type-check` exit 0, with the script name echoed in the output ('> tsc --noEmit && tsc -p tsconfig.test.json') so it was not a zero-match no-op. First attempt exited 2 on TS2307/TS6305 unbuilt-closure errors only; fixed by `pnpm --filter '@object-ui/app-shell^...' build` (exit 0) — not a defect in this change. (4) REVERSE VERIFICATION on a real commit, never against uncommitted edits: committed 85c289455, then `git checkout origin/main -- block-types.ts`; mutation confirmed on disk by grepping BOTH the injected and the removed text (injected line count 0, reverted line count 1 — not a bare diff --stat), re-ran -> 'Tests 2 failed | 33 passed (35)', exit 1. Predicted direction was plain red and that is what happened. Restored with `git checkout HEAD -- block-types.ts`, re-confirmed on disk (injected 1, removed 0), `git diff HEAD --stat` EMPTY, re-ran -> 35 passed, exit 0. LEGS THAT DO NOT DISCRIMINATE, named: all 30 cases of block-config.test.ts stay green in both states (derived coverage, either direction satisfies it); the new file's 'both spellings are real members of the pinned spec enum' case (a fact about the spec, not about this change); and BOTH alias-renderability cases, deliberately — they assert the registry and renderer this PR does not touch, so they must be green before and after, and the day they go red the cause is a deleted registration. (5) GATES, each quoting its own verdict line, exit codes captured before any pipe: check:control-bytes 'OK (scanned 4855 tracked text file(s); skipped 85 binary)'; check:spec-symbols 'spec symbol derivation: 1298 files scanned against 4959 spec export names'; check:phantom-deps 'Every in-scope import is declared by the package that publishes it'; check:i18n-keys 'every in-scope call-site key resolves against the en pack (2928 keys)'; check:i18n-dead-keys (a REPORT, not a gate, per its own footer) exit 0; node scripts/check-changeset-presence.mjs '1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)' exit 0. (6) LINT: the touched package's own gate ran IN FULL, not narrowed — `eslint .` in @object-ui/app-shell, measured from --format json output: 939 files linted, 0 errors, 2599 warnings (the repo-wide un-capped baseline .github/workflows/lint.yml documents). One new warning, an `any` type-argument on a React.ComponentType annotation in the new test. DECLARED NARROWING: the other 39 packages' lint was not run locally. Invariance evidence rather than assumption — the root eslint.config.js enables no type-aware linting (tseslint.configs.recommended, no project/projectService in languageOptions), so an edit confined to packages/app-shell cannot move the verdict on any untouched file in another package. CI runs the whole farm regardless.",
"open_questions": [],
"out_of_scope_findings": [
"filed as #5837 (label `finding`, unassigned, no pm:queue): the page-block canvas draws a node's icon and colour tone from BLOCK_TYPE_META, so a type that renders fine but is excluded from the palette shows the generic UnknownBlockIcon and the neutral misc tone in the outline. Pre-existing, not introduced here — before this card it was the CANONICAL record:discussion that read this way, i.e. every page the platform generates for itself; this change moves it onto the rarer legacy alias, reducing how often it is seen without closing it. Not folded in: a fix needs a new alias-display mechanism, since a second BLOCK_TYPE_META entry would break block-config.test.ts's 'no type is both offered and excluded'. Disclosed in the changeset and the PR body.",
"NOT FILED, reported here instead: block-types.ts carries a pre-existing unused import (`Bot`, line 33) — verified unchanged on origin/main, so not introduced by this PR. Left alone and deliberately not filed: it is one of 53 @typescript-eslint/no-unused-vars warnings in @object-ui/app-shell alone, part of the repo-wide warning baseline .github/workflows/lint.yml explicitly declines to cap ('--max-warnings is deliberately not set'). An issue for this single instance would duplicate a known and deliberately accepted stance rather than report anything new. Flagging it so the judgement is PM's, not silently mine."
]
}
Activity
os-zhuang commentedon Aug 21, 2026
Triage (first-touch): routed to the decision inbox (needs-user-decision, domain:ui, type Task). The palette currently advertises the compatibility alias and explicitly excludes the canonical name — which way it points changes what authors see and what new pages get authored with, an author-facing naming call on the manual floor (small, one-letter answer). Chinese four-facet analysis below.
os-decision-facets(四棱卡面块;标记按字面文本写入)
一句话问题:同一个「讨论/动态」组件有两个名字,官方正名是 discussion,兼容旧名是 chatter —— 而组件面板上架的偏偏是旧名,正名反被明示排除;新页面从此都用旧名写成。
选项与真实代价:
置信缺口(本分析看不见什么):「Salesforce 熟悉感」对当前目标客户的实际获客价值无法从代码测得 —— 这正是要你裁的原因;存量用户页面里手拖 chatter 块的数量未测。裁后执行:A 则一张 S 卡(BLOCK_TYPE_META 换名 + PALETTE_EXCLUSIONS 反转 + block-config.test 断言随动 + 4935 姊妹残留顺检),B 则本卡关 won't-fix 并把裁决写进排除注释。
Generated by Claude Code
huangyiirene commentedon Aug 22, 2026
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat,
session_01ApyDuQY2fkunMCqXiqvBhR)The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Option A — the palette offers the canonical name.
record:discussionis offered in the page-editor palette andrecord:chatterbecomes the explicitly excluded compatibility alias, inverting the currentPALETTE_EXCLUSIONSstate. The author-facing label changes from "Chatter feed" to "Discussion"; the alias stays renderable for existing schemas, just no longer advertised. Per the triage execution note this is an S-size card:BLOCK_TYPE_METArename,PALETTE_EXCLUSIONSinversion, theblock-config.test.tsassertion following along, and a check of the #4935 siblingelement:filterresidue in the same file.State:
needs-user-decisionremoved →pm:queue(ready for dispatch).Generated by Claude Code
claude commentedon Aug 23, 2026
Claim —
domain:uiexecution seat. PM round 29, sessionsession_01EuPCi56cnGyykygi3z9w4m, branchclaude/issue-5495-palette-canonical-discussion. Default tier.Executing the 2026-08-22 maintainer ruling: Option A — the palette offers the canonical name.
record:discussionis offered;record:chatterbecomes the explicitly excluded compatibility alias, inverting the currentPALETTE_EXCLUSIONSstate. The label moves "Chatter feed" → "Discussion". ⛔ The alias stays renderable for existing schemas — this changes what is advertised, not what works.S-size scope as the triage execution note records it:
BLOCK_TYPE_METArename ·PALETTE_EXCLUSIONSinversion · theblock-config.test.tsassertion following along · and a check of the #4935 siblingelement:filterresidue in the same file.PALETTE_EXCLUSIONS['element:filter']was already deleted by #5529, which had to touch this same file once the enum member disappeared. So the check is to confirm that and report what (if anything) is left, ⛔ not to re-delete something already gone.Hot-file serialisation: #4935 is held behind this card — both land in
packages/app-shell/src/views/metadata-admin/previews/block-types.ts.Generated by Claude Code
fix(app-shell): offer canonical `record:discussion` in the page palet…
os-zhuang commentedon Aug 23, 2026
os-dev-report
{ "issue": 5495, "status": "done", "branch": "claude/issue-5495-palette-canonical-discussion", "pr": "https://github.com/objectstack-ai/objectui/pull/5838", "premise_still_valid": true, "summary": "Executed the 2026-08-22 maintainer ruling (Option A) in packages/app-shell/src/views/metadata-admin/previews/block-types.ts: BLOCK_TYPE_META now offers the canonical 'record:discussion' labelled \"Discussion\" (was 'record:chatter' / \"Chatter feed\"), and PALETTE_EXCLUSIONS now excludes 'record:chatter' as the compatibility alias — inverting the pair. Icon and category are unchanged. The alias stays fully renderable: nothing in plugin-detail was touched, and a new test (previews/__tests__/palette-discussion-alias.test.tsx) pins that the registry still resolves 'record:chatter' to the SAME renderer function object as the canonical name and that an alias schema still renders the discussion panel — so 'no longer offered' cannot drift into 'no longer rendered'. block-config.test.ts needed no edit and that is the point: it derives palette coverage from PageComponentType and is satisfied by either direction of this pair, which is why the direction now has a test of its own. Scope item 4 confirmed without acting: 'element:filter' has zero hits in block-types.ts on current main — #5529 already deleted PALETTE_EXCLUSIONS['element:filter'], exactly as #4935's 2026-08-22 unlock comment records; nothing re-deleted, #4935's remaining elements.tsx residue left alone. Changeset added (minor, @object-ui/app-shell) declaring the label change, the offered-block change, and the one knock-on below.", "tests": "All from repo root; gate union re-run on the FINAL commit 85c289455 with a clean tree. (1) SPEC PIN, counter-probed before relying on it — resolved @objectstack/spec = 17.2.0, PageComponentType.options = 34 members; 'record:discussion' -> true, 'record:chatter' -> true, 'record:details' -> true (known-present), 'element:filter' -> false (genuinely retired), 'zzNotARealType' -> false (never existed). Two trues and two falses from one probe, so a broken probe cannot read as passing. (2) TESTS: `pnpm exec vitest run <palette-discussion-alias.test.tsx> <block-config.test.ts>` -> 'Test Files 2 passed (2) / Tests 35 passed (35)', exit 0. Broader: `pnpm exec vitest run packages/app-shell/src/views/metadata-admin/previews apps/console/src/__tests__/public-contract.test.ts packages/app-shell/src/utils/__tests__/pageSchemaIntrospect.test.ts` -> 'Test Files 40 passed (40) / Tests 481 passed (481)', exit 0. (3) TYPECHECK: `pnpm --filter @object-ui/app-shell type-check` exit 0, with the script name echoed in the output ('> tsc --noEmit && tsc -p tsconfig.test.json') so it was not a zero-match no-op. First attempt exited 2 on TS2307/TS6305 unbuilt-closure errors only; fixed by `pnpm --filter '@object-ui/app-shell^...' build` (exit 0) — not a defect in this change. (4) REVERSE VERIFICATION on a real commit, never against uncommitted edits: committed 85c289455, then `git checkout origin/main -- block-types.ts`; mutation confirmed on disk by grepping BOTH the injected and the removed text (injected line count 0, reverted line count 1 — not a bare diff --stat), re-ran -> 'Tests 2 failed | 33 passed (35)', exit 1. Predicted direction was plain red and that is what happened. Restored with `git checkout HEAD -- block-types.ts`, re-confirmed on disk (injected 1, removed 0), `git diff HEAD --stat` EMPTY, re-ran -> 35 passed, exit 0. LEGS THAT DO NOT DISCRIMINATE, named: all 30 cases of block-config.test.ts stay green in both states (derived coverage, either direction satisfies it); the new file's 'both spellings are real members of the pinned spec enum' case (a fact about the spec, not about this change); and BOTH alias-renderability cases, deliberately — they assert the registry and renderer this PR does not touch, so they must be green before and after, and the day they go red the cause is a deleted registration. (5) GATES, each quoting its own verdict line, exit codes captured before any pipe: check:control-bytes 'OK (scanned 4855 tracked text file(s); skipped 85 binary)'; check:spec-symbols 'spec symbol derivation: 1298 files scanned against 4959 spec export names'; check:phantom-deps 'Every in-scope import is declared by the package that publishes it'; check:i18n-keys 'every in-scope call-site key resolves against the en pack (2928 keys)'; check:i18n-dead-keys (a REPORT, not a gate, per its own footer) exit 0; node scripts/check-changeset-presence.mjs '1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)' exit 0. (6) LINT: the touched package's own gate ran IN FULL, not narrowed — `eslint .` in @object-ui/app-shell, measured from --format json output: 939 files linted, 0 errors, 2599 warnings (the repo-wide un-capped baseline .github/workflows/lint.yml documents). One new warning, an `any` type-argument on a React.ComponentType annotation in the new test. DECLARED NARROWING: the other 39 packages' lint was not run locally. Invariance evidence rather than assumption — the root eslint.config.js enables no type-aware linting (tseslint.configs.recommended, no project/projectService in languageOptions), so an edit confined to packages/app-shell cannot move the verdict on any untouched file in another package. CI runs the whole farm regardless.", "open_questions": [], "out_of_scope_findings": [ "filed as #5837 (label `finding`, unassigned, no pm:queue): the page-block canvas draws a node's icon and colour tone from BLOCK_TYPE_META, so a type that renders fine but is excluded from the palette shows the generic UnknownBlockIcon and the neutral misc tone in the outline. Pre-existing, not introduced here — before this card it was the CANONICAL record:discussion that read this way, i.e. every page the platform generates for itself; this change moves it onto the rarer legacy alias, reducing how often it is seen without closing it. Not folded in: a fix needs a new alias-display mechanism, since a second BLOCK_TYPE_META entry would break block-config.test.ts's 'no type is both offered and excluded'. Disclosed in the changeset and the PR body.", "NOT FILED, reported here instead: block-types.ts carries a pre-existing unused import (`Bot`, line 33) — verified unchanged on origin/main, so not introduced by this PR. Left alone and deliberately not filed: it is one of 53 @typescript-eslint/no-unused-vars warnings in @object-ui/app-shell alone, part of the repo-wide warning baseline .github/workflows/lint.yml explicitly declines to cap ('--max-warnings is deliberately not set'). An issue for this single instance would duplicate a known and deliberately accepted stance rather than report anything new. Flagging it so the judgement is PM's, not silently mine." ] }Generated by Claude Code
fix(app-shell): offer canonical `record:discussion` in the page palet…