NON-BREAKING: add org.hypercerts.claim.post lexicon#138
NON-BREAKING: add org.hypercerts.claim.post lexicon#138
Conversation
🦋 Changeset detectedLatest commit: 08e3b3c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughAdds a new Changes
Sequence Diagram(s)(silently omitted — changes are lexicon/schema/type additions without multi-component runtime control flow) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
lexicons/org/hypercerts/claim/post.json (2)
71-78:replyRefdef and its properties are missingdescriptionfields.The
replyRefobject def has no top-leveldescription, and neitherrootnorparentcarry descriptions. This is inconsistent with every other def in the repository (e.g.,org.hypercerts.claim.activity#contributor,org.hypercerts.claim.evaluation#score) and causes empty cells in the SCHEMAS.md replyRef table.✏️ Suggested addition
"replyRef": { "type": "object", + "description": "Identifies the thread root and direct parent that this post is replying to.", "required": ["root", "parent"], "properties": { - "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, - "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" } + "root": { "type": "ref", "ref": "com.atproto.repo.strongRef", "description": "The root record of the thread being replied to." }, + "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef", "description": "The direct parent record being replied to (may be the same as root for top-level replies)." } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lexicons/org/hypercerts/claim/post.json` around lines 71 - 78, Add missing description fields for the replyRef definition and its properties so schema docs render correctly: update the replyRef object (symbol: replyRef) to include a top-level "description" summarizing its purpose (e.g., points to the root and parent posts of a reply) and add "description" entries for "root" and "parent" properties (symbols: root, parent) explaining that "root" is the original thread/root record strongRef and "parent" is the immediate replied-to strongRef; keep descriptions concise and consistent with other defs like contributor/score.
30-39: Add adescriptionto theembedfield.Every other field in this lexicon has a
description, butembeddoes not — this propagates as an empty cell in SCHEMAS.md. A brief description like the one used inapp.bsky.feed.postwould make the intent clear (e.g., distinguishing why embed is singular whileattachmentsis plural).✏️ Suggested addition
"embed": { "type": "union", + "description": "The primary featured media for this post (images, video, external link, or quoted record). At most one embed per post, matching Bluesky conventions.", "refs": [🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lexicons/org/hypercerts/claim/post.json` around lines 30 - 39, The lexicon's "embed" field (type "union" with refs ["app.bsky.embed.images","app.bsky.embed.video","app.bsky.embed.external","app.bsky.embed.record","app.bsky.embed.recordWithMedia"]) is missing a description; add a concise "description" property for "embed" (similar to the description used in app.bsky.feed.post) that explains this field holds at most one embedded object and clarifies why "embed" is singular while "attachments" is plural so the intent is clear in generated documentation.scripts/create-shims.sh (1)
28-70: New embed shims are inconsistent with the existing richtext-facet shim — namespace re-export is missing.The existing
app/bsky/richtext/facet.tsshim (lines 17-18) both imports the namespace and re-exports it:import type { AppBskyRichtextFacet } from '@atcute/bluesky'; export type { AppBskyRichtextFacet }; // ← namespace re-exportThe five new embed shims only export individual members and omit the
export type { ... }namespace re-export. If any generated code doesimport { AppBskyEmbedImages } from './embed/images'(namespace-style access), it will fail to resolve.✏️ Suggested fix — add namespace re-exports (shown for images.ts; apply to all five)
import type { AppBskyEmbedImages } from '@atcute/bluesky'; +export type { AppBskyEmbedImages }; export type Main = AppBskyEmbedImages.Main; export type Image = AppBskyEmbedImages.Image; export type View = AppBskyEmbedImages.View; export type ViewImage = AppBskyEmbedImages.ViewImage;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/create-shims.sh` around lines 28 - 70, The new embed shims import the upstream namespaces (e.g. AppBskyEmbedImages, AppBskyEmbedVideo, AppBskyEmbedExternal, AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia) but fail to re-export the namespace itself, breaking consumers that do namespace-style imports; for each shim (images.ts, video.ts, external.ts, record.ts, recordWithMedia.ts) add a namespace re-export line after the import — e.g. add "export type { AppBskyEmbedImages };" (and the corresponding symbol for each file: AppBskyEmbedVideo, AppBskyEmbedExternal, AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia) while keeping the existing individual export type lines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lexicons/org/hypercerts/claim/post.json`:
- Around line 1-80: ERD.puml is missing the new post entity for the lexicon
org.hypercerts.claim.post; update ERD.puml to add a "post" entity that models
the record (omit the cosmetic facets field), and add relationships from replyRef
→ com.atproto.repo.strongRef and attachments → org.hypercerts.defs#uri and
org.hypercerts.defs#smallBlob (use the replyRef name and attachments array to
guide the relationship cardinality/labels). Ensure the entity name references
org.hypercerts.claim.post (or simply "post") and include links to
com.atproto.repo.strongRef and org.hypercerts.defs entries per project ERD
style.
In `@SCHEMAS.md`:
- Around line 252-255: The schema table for the replyRef properties is missing
descriptions: update the Description cells for the `root` and `parent`
properties (the two `ref` fields) to clearly state their meaning and usage —
e.g., `root` is a reference to the top-level thread/root message ID and `parent`
is a reference to the immediate parent message ID (used to reconstruct reply
hierarchy); ensure the wording matches other lexicon defs in SCHEMAS.md and
mention they are message refs/IDs so generated docs are informative.
- Around line 240-244: Fix two copy issues in the post lexicon table: add the
missing period after the abbreviation in the `facets` description so "etc)"
becomes "etc.)", and populate the empty description cell for the `embed` row
with a short explanatory sentence (for example: "Featured embed for this post —
images, video, external link, or quoted record."). Update the table rows for
`facets` and `embed` accordingly so the generated docs include the corrected
punctuation and the new embed description.
---
Nitpick comments:
In `@lexicons/org/hypercerts/claim/post.json`:
- Around line 71-78: Add missing description fields for the replyRef definition
and its properties so schema docs render correctly: update the replyRef object
(symbol: replyRef) to include a top-level "description" summarizing its purpose
(e.g., points to the root and parent posts of a reply) and add "description"
entries for "root" and "parent" properties (symbols: root, parent) explaining
that "root" is the original thread/root record strongRef and "parent" is the
immediate replied-to strongRef; keep descriptions concise and consistent with
other defs like contributor/score.
- Around line 30-39: The lexicon's "embed" field (type "union" with refs
["app.bsky.embed.images","app.bsky.embed.video","app.bsky.embed.external","app.bsky.embed.record","app.bsky.embed.recordWithMedia"])
is missing a description; add a concise "description" property for "embed"
(similar to the description used in app.bsky.feed.post) that explains this field
holds at most one embedded object and clarifies why "embed" is singular while
"attachments" is plural so the intent is clear in generated documentation.
In `@scripts/create-shims.sh`:
- Around line 28-70: The new embed shims import the upstream namespaces (e.g.
AppBskyEmbedImages, AppBskyEmbedVideo, AppBskyEmbedExternal, AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia) but fail to re-export the namespace itself,
breaking consumers that do namespace-style imports; for each shim (images.ts,
video.ts, external.ts, record.ts, recordWithMedia.ts) add a namespace re-export
line after the import — e.g. add "export type { AppBskyEmbedImages };" (and the
corresponding symbol for each file: AppBskyEmbedVideo, AppBskyEmbedExternal,
AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia) while keeping the existing
individual export type lines.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.changeset/add-post-lexicon.mdSCHEMAS.mdlexicons/org/hypercerts/claim/post.jsonscripts/create-shims.sh
| { | ||
| "lexicon": 1, | ||
| "id": "org.hypercerts.claim.post", | ||
| "defs": { | ||
| "main": { | ||
| "type": "record", | ||
| "description": "Record containing a hypercerts post, e.g. an update, a report, a comment.", | ||
| "key": "tid", | ||
| "record": { | ||
| "type": "object", | ||
| "required": ["text", "createdAt"], | ||
| "properties": { | ||
| "text": { | ||
| "type": "string", | ||
| "maxLength": 50000, | ||
| "maxGraphemes": 5000, | ||
| "description": "The primary post content. May be an empty string, if there are embeds." | ||
| }, | ||
| "facets": { | ||
| "type": "array", | ||
| "description": "Annotations of text (mentions, URLs, hashtags, etc)", | ||
| "items": { "type": "ref", "ref": "app.bsky.richtext.facet" } | ||
| }, | ||
| "replies": { | ||
| "type": "array", | ||
| "description": "The subjects that this post is in reply to. Each entry identifies a thread root and the direct parent being replied to.", | ||
| "items": { "type": "ref", "ref": "#replyRef" }, | ||
| "maxLength": 10 | ||
| }, | ||
| "embed": { | ||
| "type": "union", | ||
| "refs": [ | ||
| "app.bsky.embed.images", | ||
| "app.bsky.embed.video", | ||
| "app.bsky.embed.external", | ||
| "app.bsky.embed.record", | ||
| "app.bsky.embed.recordWithMedia" | ||
| ] | ||
| }, | ||
| "labels": { | ||
| "type": "union", | ||
| "description": "Self-label values for this post. Effectively content warnings.", | ||
| "refs": ["com.atproto.label.defs#selfLabels"] | ||
| }, | ||
| "tags": { | ||
| "type": "array", | ||
| "description": "Additional hashtags, in addition to any included in post text and facets.", | ||
| "maxLength": 8, | ||
| "items": { "type": "string", "maxLength": 640, "maxGraphemes": 64 } | ||
| }, | ||
| "attachments": { | ||
| "type": "array", | ||
| "description": "The files, documents, or external references attached to this post.", | ||
| "items": { | ||
| "type": "union", | ||
| "refs": [ | ||
| "org.hypercerts.defs#uri", | ||
| "org.hypercerts.defs#smallBlob" | ||
| ] | ||
| }, | ||
| "maxLength": 100 | ||
| }, | ||
| "createdAt": { | ||
| "type": "string", | ||
| "format": "datetime", | ||
| "description": "Client-declared timestamp when this post was originally created." | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "replyRef": { | ||
| "type": "object", | ||
| "required": ["root", "parent"], | ||
| "properties": { | ||
| "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, | ||
| "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, check if ERD.puml exists and its current state
if [ -f "ERD.puml" ]; then
echo "=== ERD.puml exists ==="
wc -l ERD.puml
echo ""
echo "=== Checking for post-related references in ERD.puml ==="
grep -n "post\|Post" ERD.puml || echo "(no 'post' references found)"
else
echo "ERD.puml does not exist"
fi
echo ""
echo "=== Checking if ERD.puml was modified in this PR ==="
git diff --name-only 2>/dev/null | head -20
echo ""
echo "=== Repository structure (checking for diagram files) ==="
find . -maxdepth 2 -name "*.puml" -o -name "*ERD*" -o -name "*erd*" 2>/dev/null | head -20Repository: hypercerts-org/hypercerts-lexicon
Length of output: 411
🏁 Script executed:
#!/bin/bash
# Check the git log to see recent changes to ERD.puml
echo "=== Recent git history for ERD.puml ==="
git log --oneline --all -- ERD.puml 2>/dev/null | head -10 || echo "No git history available"
echo ""
echo "=== Files in the repository root ==="
ls -la | head -30Repository: hypercerts-org/hypercerts-lexicon
Length of output: 2522
🏁 Script executed:
#!/bin/bash
# Read the ERD.puml file to see its current structure
echo "=== ERD.puml content ==="
cat -n ERD.pumlRepository: hypercerts-org/hypercerts-lexicon
Length of output: 9787
🏁 Script executed:
#!/bin/bash
# Check the git diff for the commit that added post.json to see if ERD.puml was modified
echo "=== Git diff for d597c87 (post.json commit) ==="
git show d597c87 --stat
echo ""
echo "=== Did post.json commit touch ERD.puml? ==="
git show d597c87 --name-only | grep -i "erd\|post"Repository: hypercerts-org/hypercerts-lexicon
Length of output: 7447
Add post entity to ERD.puml.
The new post lexicon introduces a record type with relationships (replyRef → com.atproto.repo.strongRef, attachments → org.hypercerts.defs#{uri,smallBlob}), but ERD.puml was not updated. Add the post entity and its relationships to the diagram, omitting the facets field (which is a cosmetic annotation). Per coding guidelines, ERD.puml must reflect all entity relationships whenever lexicons are added or modified.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lexicons/org/hypercerts/claim/post.json` around lines 1 - 80, ERD.puml is
missing the new post entity for the lexicon org.hypercerts.claim.post; update
ERD.puml to add a "post" entity that models the record (omit the cosmetic facets
field), and add relationships from replyRef → com.atproto.repo.strongRef and
attachments → org.hypercerts.defs#uri and org.hypercerts.defs#smallBlob (use the
replyRef name and attachments array to guide the relationship
cardinality/labels). Ensure the entity name references org.hypercerts.claim.post
(or simply "post") and include links to com.atproto.repo.strongRef and
org.hypercerts.defs entries per project ERD style.
|
According to my investigation the Style Guide Check errors are false positives... |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ERD.puml (1)
350-351: Consider modelingrepliesas a generic strongRef relationship.
repliesis defined viareplyRef→com.atproto.repo.strongRef, which isn’t limited to just activities/collections. If replies can target other records (e.g., posts), the ERD may be misleading. Consider pointing to a generic strongRef (or adding additional relationships) to match the schema.As per coding guidelines, “When ERD.puml is modified, verify that all relationships shown are valid based on JSON lexicon schemas.”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ERD.puml` around lines 350 - 351, The ERD currently maps post::replies to specific targets (activity, collection) but the schema defines replies via replyRef -> com.atproto.repo.strongRef and can target arbitrary records; update ERD.puml so post::replies points to a generic strongRef entity (or add explicit additional relationships) instead of only activity and collection to match replyRef/com.atproto.repo.strongRef in the JSON lexicon and ensure every shown relationship is validated against the schema.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@ERD.puml`:
- Around line 350-351: The ERD currently maps post::replies to specific targets
(activity, collection) but the schema defines replies via replyRef ->
com.atproto.repo.strongRef and can target arbitrary records; update ERD.puml so
post::replies points to a generic strongRef entity (or add explicit additional
relationships) instead of only activity and collection to match
replyRef/com.atproto.repo.strongRef in the JSON lexicon and ensure every shown
relationship is validated against the schema.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
ERD.pumlSCHEMAS.mdlexicons/org/hypercerts/claim/post.jsonscripts/create-shims.sh
| "@hypercerts-org/lexicon": minor | ||
| --- | ||
|
|
||
| Add org.hypercerts.claim.post lexicon for updates, reports, and comments on hypercerts records |
There was a problem hiding this comment.
not sure about the .claim. domain because this can point to many things, including evidence, that aren't directly the claim
There was a problem hiding this comment.
yes, I feel like the whole folder structure isn't super ideal yet, but don't have a very clear alternative.
regarding evidence, that is claim.attachment, so claim.post would for that. I agree with you in general though... will think about the folder structure more
| "type": "object", | ||
| "required": ["text", "createdAt"], | ||
| "properties": { | ||
| "text": { |
There was a problem hiding this comment.
The description is in opposition with required. Requiring an empty string doesn't make much sense
| "maxLength": 8, | ||
| "items": { "type": "string", "maxLength": 640, "maxGraphemes": 64 } | ||
| }, | ||
| "attachments": { |
There was a problem hiding this comment.
and this is functionally different from embeds?
There was a problem hiding this comment.
yes, there is just one main embed, but if you want to add just more files, you can with the attachment.
629947d to
6f5e5e9
Compare
|
Discussed and agreed to hold fire for now as we might just reuse |
|
@bitbeckers how did you implement updates in MaEarth? |
Add a post record type for updates, reports, and comments on hypercerts records. Modeled after app.bsky.feed.post with hypercerts-specific extensions (multi-reply, attachments). Also adds type shims for app.bsky.embed.* and com.atproto.label.defs external lexicon references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add descriptions to embed, replyRef, root, and parent fields - Fix "etc)" to "etc.)" in facets description - Add namespace re-exports to embed/label type shims for consistency - Add post entity and relationships to ERD.puml - Regenerate SCHEMAS.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…AS.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6f5e5e9 to
08e3b3c
Compare
Summary
org.hypercerts.claim.postlexicon for updates, reports, and comments on hypercerts recordsapp.bsky.embed.*andcom.atproto.label.defsexternal lexicon referencesDesign
Modeled after
app.bsky.feed.postwith hypercerts-specific extensions:textfacetsrepliesembedlabelstagsattachmentscreatedAtWhy a single
embed(not an array)The
embedfield is deliberately singular, matching Bluesky's design. This separates concerns between:embed: one rich, featured media item with full rendering support (image gallery, video player, link card with preview, quoted record)attachments: supplementary references (additional URLs, documents, files)This distinction is semantically cleaner than a flat array of embeds and maintains compatibility with Bluesky clients that expect a single embed to render. For example, a post about a reforestation update could have an
embedwith before/after photos andattachmentslinking to the full report PDF, a YouTube timelapse, and GPS data.MaEarth adoption path
This schema can replace several of MaEarth's custom types defined in
types.maearth.ts:MaEarthUpdateComment→ direct replacementbodytextsubject: { uri, cid }replies[].root/replies[].parentcreatedAtcreatedAtBy adopting
org.hypercerts.claim.post, MaEarth's update/comment pattern gains rich text (facets), embeds, tags, attachments, multi-language support, and content labels — all for free.MaEarthPostMetadata→ mostly replaceableembeds: External[]embed(singular) +attachmentsembed, overflow URLs go inattachmentsasorg.hypercerts.defs#uricreatedAtcreatedAtMaEarth currently uses an array of
AppBskyEmbedExternal.Externalfor multiple link previews. With this schema, the primary embed goes inembedand additional URLs go inattachments.Test plan
npm run checkpasses (gen-api, lint, typecheck, build, test)🤖 Generated with Claude Code
Summary by CodeRabbit