Skip to content

fix(plugin-audit): describe sys_comment reactions and mentions by the shape they store (#20558) - #20605

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-20558-comment-reactions-description
Sep 29, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-20558-comment-reactions-description

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #20558

Clause-②: no

The description of two sys_comment fields is served metadata (field help, and what an AI client reads before it seeds a comment). Both named a shape no producer writes. They now name the stored shape, and the en translation bundle is regenerated from the source.

Field Description was Description is now
reactions JSON array of emoji reaction objects JSON object mapping each emoji to the list of user ids who reacted
mentions JSON array of @mention objects JSON array of the user ids @mentioned in the comment

Files: packages/plugins/plugin-audit/src/objects/sys-comment.object.ts (2 lines), packages/plugins/plugin-audit/src/translations/en.objects.generated.ts (regenerated), .changeset/20558-comment-reactions-mentions-description.md (patch on @objectstack/plugin-audit). Landing point is the one the card names; no producer lives in another package of this repository.

Measurement (premise check, before the edit)

Trees read: objectstack c876a742 (this PR's base) and objectui bf7ab35c (a read-only shallow clone made through the session git proxy; the REST API answers 403 for that repository, plain git does not).

  • reactions, this repository: no producer or reader. git grep -i reactions over the tree, minus CHANGELOGs and generated bundles, finds only the field declaration, ADR and docs prose, and unrelated enableReactions UI props.
  • reactions, objectui packages/app-shell/src/views/RecordDetailView.tsx: parseReactions reads a JSON object of emoji -> string[], and the click handler writes JSON.stringify(storedReactions(...)), the same map (storedReactions returns a string-keyed map of string arrays). packages/collaboration/src/CommentThread.tsx types it as a string-keyed map of string arrays. The card's premise holds.
  • mentions, producer: the same file's handleAddComment and handleAddReply (the only two sys_comment creates in objectui) write mentions: JSON.stringify(mentionIds), and extractMentions in packages/plugin-detail/src/extractMentions.ts returns a de-duplicated string[] of user ids. No objects. This disagrees with the old sentence, so per the triage rule mentions rides in this PR.
  • mentions, consumer in this repository: writeCommentMentions in packages/plugins/plugin-audit/src/audit-writers.ts reads the JSON and accepts an array of id strings or an array of objects with an id key. Every in-repo test value is an id string ('["user-2"]'). The description names only the one shape the producer writes; the consumer's object tolerance is not advertised (one strict contract, not two dialects).
  • Not measured: any producer outside objectstack and objectui (the cloud repository was not read); a runtime probe of what the console shows for the old array shape (the card marks that step as read inference, and it stays so).

Translations

node scripts/check-i18n-bundles.mjs --write rewrote only en.objects.generated.ts. The other eight packages regenerated with no diff. The zh-CN, ja-JP and es-ES bundles keep their hand-written values (merge mode), and pnpm check:i18n and pnpm check:i18n-stale-fill are green without touching them, so per the dispatch they are not hand-translated here. Six strings therefore still say "array of ... objects" and now contradict the English: mentions and reactions help in each of the three locales (zh-CN lines 218 and 222, ja-JP lines 218 and 222, es-ES lines 218 and 222). This is listed in the report as an open question for the PM seat.

Verification (final head e83328b)

  • Derived gate list: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack gives 57 commands (the seat's 50 plus 7 that the changeset file adds). All 57 were run one by one with the exit code captured first; all exit 0 at e83328b6. --ran reconciliation with exit codes: 57 derived, 57 run, 0 NOT-MEASURED, 0 UNRUN. One first attempt of pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: nine unrelated packages had no dist/); after building those nine it exited 0 (104 entry points, 66 packages).
  • pnpm --filter @objectstack/plugin-audit test: 25 files, 363 tests passed. pnpm --filter @objectstack/plugin-audit typecheck: exit 0 (both run at 236bae38; the one later commit changes only the changeset text).
  • One-time ablation (nothing kept): with the en bundle put back to the base text, on-disk mutation confirmed by grep (old text 1, new text 0), node scripts/check-i18n-bundles.mjs --filter=audit exits 1 with plugins/plugin-audit DRIFTED (1). Restored with git checkout HEAD -- path; the blob hash matches HEAD (7c457527...) and git diff HEAD is empty. Direction observed: red, as expected.
  • Line budget: 20 additions, 4 deletions, 3 files; no skills/** file touched.

Acceptance notes

  • The one open item is the three stale translated locales above; nothing else is left out of scope.

Seat append — patch round 1 (head 0cebc286, the dev's text, appended by the domain:services seat)

The seat answered the open question above with option A, so the six translated help strings are rewritten on this branch. This section supersedes the Translations and Acceptance notes paragraphs above where they call the three locales stale.

Values only: no key added or dropped, no label and no other string touched. Exactly six help values changed (two per file, 6 additions and 6 deletions):

Locale mentions help reactions help
zh-CN 评论中被 @ 提及的用户 ID 的 JSON 数组 将每个表情映射到对其做出回应的用户 ID 列表的 JSON 对象
ja-JP コメント内で @メンションされたユーザー ID の JSON 配列 各絵文字を、リアクションしたユーザー ID のリストに対応付ける JSON オブジェクト
es-ES Matriz JSON de los id de usuario mencionados con @ en el comentario. Objeto JSON que asigna cada emoji a la lista de id de usuario de quienes reaccionaron.

Wording follows each bundle's own habits: the terms for a user id match the existing user_id help in the same file, es-ES keeps its trailing period as 20 of its 23 help strings do, and zh-CN and ja-JP stay period-free. The faithfulness of the translations was read by the author only, with no native-speaker review.

The changeset gains one clause saying the translated help texts follow; the level stays patch.

Proof the tool keeps them: after the edit was committed, node scripts/check-i18n-bundles.mjs --write regenerated all nine packages and left git status --porcelain empty and git diff HEAD at zero lines. Against the previous head, the diff of the three translation files is those six help lines and nothing else.

At head 0cebc286: pnpm check:i18n, pnpm check:i18n-stale-fill and pnpm check:nul-bytes exit 0, pnpm --filter @objectstack/plugin-audit test passes (25 files, 363 tests), and all 57 derived gate commands exit 0 (the derived list is unchanged by this round; --ran reconciliation: 57 run, 0 NOT-MEASURED). Whole-PR diff: 6 files, 26 additions, 10 deletions.

Seat append — Acceptance notes (added at the at-tier review's request, record 5885205176)

  • Noted, not filed: the in-repo consumer writeCommentMentions (plugin-audit audit-writers.ts) also accepts array entries that are objects with an id key, a lenient-consumer tolerance that no producer in this repository writes. This PR deliberately does not advertise it: the new description names only the id-string array. No public door answers wrong today, so it is not a card. Dedupe words: writeCommentMentions object entries · sys_comment mentions id objects tolerance · collab.mention parse leniency.

Generated by Claude Code

… shape their producer stores (#20558)

reactions is a JSON object mapping each emoji to the user ids who reacted
(objectui RecordDetailView reads and writes exactly that map); mentions is a
JSON array of user id strings (the same producer writes JSON.stringify of an
id list, and writeCommentMentions consumes it). Translations regenerate in the
next commit.

Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H
Co-authored-by: Claude <noreply@anthropic.com>
…or the sys_comment description fix (#20558)

Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H
Co-authored-by: Claude <noreply@anthropic.com>
…ot ping an at-mention (#20558)

Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Sep 29, 2026
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-audit, touching 2 documentable anchor(s).

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/plugins/packages.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/ui/setup-app.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

⛔ 4 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v14.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v16.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-0.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-1.mdx (via sys_comment (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 9 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from e6499353f06068d031df2e5e77c5f9b2a4a78292 — the merge of head 0cebc286c3d8fa70e82969f203d774d334a2d589 into base 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e6499353f06068d031df2e5e77c5f9b2a4a78292 && git checkout e6499353f06068d031df2e5e77c5f9b2a4a78292
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5 0cebc286c3d8fa70e82969f203d774d334a2d589 && git checkout -B drift-repro 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5 && git merge --no-ff 0cebc286c3d8fa70e82969f203d774d334a2d589

node scripts/docs-audit/affected-docs.mjs --json 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 7a1faf1a5d213cd3fb3c71320d1fb2f9f25f50d5 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…ns help into zh-CN, ja-JP and es-ES (#20558)

Values only: the six help strings that still named an array of objects now
follow the English descriptions. No key added or dropped, no label touched.

Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0cebc286c3d8fa70e82969f203d774d334a2d589
Local-runs: none

Inputs read: card #20558 (body and all five comments, the triage 5883386484, the claim 5884359350, the two os-dev-report comments 5884888328 and 5885081080, the seat ACCEPT 5885116533), PR #20605 (body, six-file list, the net diff origin/main... head, 6 files, +26 / −10), and the check-runs on the head. Repository reads were git-object reads of objectstack-ai/objectstack at the head only; no other repository was read.

① Derived judgments

Accept-set changes: none — right. The diff edits two description string values on Field.textarea declarations of SysComment (packages/plugins/plugin-audit/src/objects/sys-comment.object.ts, mentions and reactions). No key added or removed, no type, required, validation rule, hook or stored value changes. The one in-repo consumer, writeCommentMentions in audit-writers.ts, is untouched, so what the runtime accepts is identical before and after.

Public-surface changes: the served help text for two fields, in five bundles — right, and non-breaking. The source description, the regenerated en bundle, and the hand-written zh-CN, ja-JP, es-ES bundles. No export, route, schema key or registration moves.

  • reactions → JSON object mapping each emoji to the list of user ids who reacted: the triage sentence verbatim (5883386484). At the head this repository holds no producer or reader of the field (the only hits for the name are the declaration and the bundles), so the stored map shape rests on the card's own evidence, filed by the objectui seat from its producer. Right.
  • mentions → JSON array of the user ids @mentioned in the comment: rode under triage's rule. Judged against the in-repo consumer: writeCommentMentions parses the JSON string, takes string entries as ids (its primary branch) and reads id off object entries (a tolerance), and every in-repo test value is an id-string array (audit-writers.test.ts lines 1018 and 1948, audit-hook-object-scope.test.ts line 599). The new sentence names exactly the id-string array and does not advertise the tolerated object dialect — claim narrower than tolerance, one dialect declared. Right.
  • en.objects.generated.ts: both new help values equal the two new descriptions byte for byte, which is the tool's rule for the default locale (a copy of the source). Right.
  • Six translated help values (patch round 1): values only, every key and label intact — the three-file diff is six minus and six plus lines, all help. Read for faithfulness here: zh-CN 评论中被 @ 提及的用户 ID 的 JSON 数组 and 将每个表情映射到对其做出回应的用户 ID 列表的 JSON 对象, ja-JP コメント内で @メンションされたユーザー ID の JSON 配列 and 各絵文字を、リアクションしたユーザー ID のリストに対応付ける JSON オブジェクト, es-ES Matriz JSON de los id de usuario mencionados con @ en el comentario. and Objeto JSON que asigna cada emoji a la lista de id de usuario de quienes reaccionaron. — each renders the English sentence, using the vocabulary the same bundle already uses (Matriz/Objeto, the user_id term, the es-ES trailing period). Merge mode keeps translated-locale values on regeneration (the tool's own drift message says so), so the edits are stable under --write. Right.
  • Leftovers: no copy of the old wording (emoji reaction objects, @mention objects) remains anywhere at the head outside release-owned CHANGELOGs and the changeset's own "was" column — no snapshot, doc page, skill or fixture still carries the array claim. Right.
  • Boundaries: no governed path in the file list (Governed Surface Queue Guard success); no content/docs/releases/ or CHANGELOG.md edit; 36 changed lines against the 5,000 threshold.

② Semver level

.changeset/20558-comment-reactions-mentions-description.md declares @objectstack/plugin-audit: patch. Right: @objectstack/plugin-audit is a published package (publishConfig.access: public, version 17.4.0, not private), so skip-changeset would be wrong, and patch is the floor for a fix in a released package. Nothing an author can write is removed or renamed, so no migration text and no ADR-0087 disposition marker are owed. The body carries no model identifier and no tag-shaped fragment; its (#20558) title reference follows the convention 616 of the 968 changesets on main use; its claim that the collab.mention hook reads the ids is true of writeCommentMentions (topic collab.mention).

The PR body's declaration reads Clause-②: no. Right: none of the four widening tells is present (no new Zod key, closed-set member, api-surface row or registry entry) and no narrowing either — the accept set is untouched in both directions. no with patch is the coherent pair.

③ Boundary flags

Round 0 report (5884888328):

  • deviations — objectui read through a read-only git clone. Recorded by the seat with containment (5885116533). Judged here: the diff does not rest on that reading. reactions stands on the card's own evidence from the objectui seat; mentions stands on in-repo evidence (the consumer's primary branch and three test values). The clone's reading is corroboration only, and the maintainer can re-verify it from an objectui-scoped seat. This review read no repository other than objectstack. Accepted as recorded.
  • deviations — 57 derived gate commands, not 50. More was run, all exit 0; the head's check-runs are the gate verdicts in any case. Accepted.
  • deviations — nine extra packages built for the check:dual-build-cjs-loads prerequisite. Local only, no diff effect. Accepted.
  • deviations — model-free commit trailer pair. Matches AGENTS.md (the pre-push hook refuses a model identifier in that pair); verified on all five commits. Accepted.
  • deviations — four pushes; behind origin/main with no merge made. WIP discipline; the head descends from base c876a742 and the PR reads mergeable: true (its blocked state is draft plus protections, not a conflict). Accepted.
  • open_questions — six stale translated help strings. Answered by the seat with option A; delivered in patch round 1 (284dc256) as values-only edits, verified in ①. Closed.
  • out_of_scope_findings — writeCommentMentions also accepts objects with an id key, which no producer writes. Agreed: a pre-existing lenient-consumer tolerance of the Prime Directive Add comprehensive test suite for Zod schema validation #12 shape, untouched by this diff, with no wrong answer reachable at a public door (id-string arrays are read correctly; the object branch is unreached by any known producer), so not a filing under Prime Directive chore: version packages #10. The seat routed it to Acceptance notes (5885116533), but the PR body's Acceptance notes section does not yet carry it — its one line names only the locale item, which the seat append superseded. Escalated to the owning seat as a body edit: append one line naming the finding and its dedupe words to the Acceptance notes. A body edit moves no head and re-owes no review; not blocking.

Round 1 report (5885081080):

  • deviations — two pushes; proof taken on the committed state. The committed form is the stronger proof (git status --porcelain empty and git diff HEAD at zero lines after --write). Accepted.
  • deviations — translation wording unreviewed by a native speaker. Reviewed here; faithful, see ①. Closed.
  • deviations — no repository other than objectstack read this round. Consistent with the report's listed reads. Accepted.
  • open_questions / out_of_scope_findings: empty.

Check-runs on the head as read for this record: 41 check-runs, 36 success, 5 skipped (Auto Label and Check PR Size on their re-run, Console Pin Gate, Build Docs, Packed-tarball smoke (opt-in)), 0 failure, 0 in progress. All seven required contexts are success (Lint & Repo Gates was in_progress on my first read and completed success before this write), and Check Changeset is success.

Implemented-by: claude/issue-20558-comment-reactions-description
Reviewed-by: session_01XY5uCwTjZj7884yYtyur4H

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 29, 2026 06:53
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit ba4648d Sep 29, 2026
50 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20558-comment-reactions-description branch September 29, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

2 participants