Project as collection sidecar - #78
Conversation
🦋 Changeset detectedLatest commit: f1c6f28 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 |
📝 WalkthroughWalkthroughThis PR refactors the collection lexicon to use an items array with recursive nesting and introduces an optional collection project sidecar (same TID) holding projectTitle, rich projectDescription, avatar, coverPhoto, and createdAt; avatar/coverPhoto were removed from the base collection. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ERD.puml (1)
204-216: Remove the deprecated project entity and its relationships from ERD.puml.The
org.hypercerts.claim.projectlexicon no longer exists in the codebase. ERD.puml still defines this deprecated entity (lines 204–216) and references it in relationships (lines 314–315), violating the coding guideline that all ERD entities must correspond to lexicons defined inlexicons/**/*.json.Note: The distinct
org.hypercerts.claim.collection.projectsidecar (line 192) correctly exists and should remain.Required changes
Remove the deprecated project dataclass definition (lines 204–216) and its relationships:
-' org.hypercerts.claim.project (DEPRECATED) -dataclass project { - !if (SHOW_FIELDS == "true") - title - shortDescription - description? - avatar? - coverPhoto? - activities[] - location? - createdAt - !endif -}Remove relationships (lines 314–315):
-project::activities --> activity -project::location --> location
🤖 Fix all issues with AI agents
In `@lexicons/org/hypercerts/claim/collection/project.json`:
- Around line 25-29: The projectDescription field currently points to
"pub.leaflet.pages.linearDocument#main" but should use the strongRef pattern so
clients submit the { uri, cid } shape shown in the README; update the
projectDescription schema to reference com.atproto.repo.strongRef (replace the
existing "ref": "pub.leaflet.pages.linearDocument#main") and keep or adjust the
description to indicate it stores a strongRef to the Leaflet linear document so
validation matches other cross-record refs (e.g., com.atproto.repo.strongRef)
used in the codebase.
In `@README.md`:
- Around line 414-418: Update the README collection docs/examples to match the
current lexicon schema by replacing the `title` property with `collectionTitle`
and adding the new fields `shortCollectionDescription`, `collectionDescription`,
and `location` (including their types, required flags, and descriptions)
wherever the collection table and examples reference `title` (notably the table
rows around `title` and the example payloads mentioned at ranges 425-447 and
477-492); ensure property names exactly match the schema (`collectionTitle`,
`shortCollectionDescription`, `collectionDescription`, `location`), update the
descriptions to reflect their purpose, and adjust any examples or notes that
reference `title` so they produce valid records against the lexicon.
| "projectDescription": { | ||
| "type": "ref", | ||
| "ref": "pub.leaflet.pages.linearDocument#main", | ||
| "description": "Rich-text description of this project, represented as a Leaflet linear document." | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's see the full project.json file to understand the structure
cat -n lexicons/org/hypercerts/claim/collection/project.jsonRepository: hypercerts-org/hypercerts-lexicon
Length of output: 2332
🏁 Script executed:
# Search for strongRef usage in other lexicon files to understand the pattern
rg "strongRef" lexicons/ -A 2 -B 2Repository: hypercerts-org/hypercerts-lexicon
Length of output: 6317
🏁 Script executed:
# Check for usage of pub.leaflet.pages.linearDocument in the codebase
rg "linearDocument" --include="*.json" --include="*.md"Repository: hypercerts-org/hypercerts-lexicon
Length of output: 518
🏁 Script executed:
# Check README.md for documentation about projectDescription
grep -n "projectDescription\|project.json\|collection" README.md | head -20Repository: hypercerts-org/hypercerts-lexicon
Length of output: 2246
🏁 Script executed:
# Look for other examples of 'ref' type fields in the codebase
rg '"type":\s*"ref"' lexicons/ -A 1 -B 1 | head -40Repository: hypercerts-org/hypercerts-lexicon
Length of output: 2482
🏁 Script executed:
# Search for Leaflet lexicon files
find lexicons -name "*leaflet*" -o -name "*linear*"Repository: hypercerts-org/hypercerts-lexicon
Length of output: 59
🏁 Script executed:
# Look for pub.bsky patterns to understand ATProto definition refs
rg "pub\.bsky" lexicons/ | head -20Repository: hypercerts-org/hypercerts-lexicon
Length of output: 59
🏁 Script executed:
# Check if there are any inline type definitions vs record references
rg '"type":\s*"ref"' lexicons/ -B 2 | grep -E "(ref|description)" | head -30Repository: hypercerts-org/hypercerts-lexicon
Length of output: 2968
🏁 Script executed:
# Search for documentation on how refs are used in ATProto
rg "richtext\|facet" lexicons/ -lRepository: hypercerts-org/hypercerts-lexicon
Length of output: 59
🌐 Web query:
ATProto lexicon how to reference external lexicon definitions in ref fields
💡 Result:
Use a full NSID (optionally with a fragment) as the ref string. Per the Lexicon spec, a ref value may be:
- a global reference: the Lexicon NSID, optionally with a “#definitionName” fragment (e.g. com.example.defs#MyType), or
- a local reference: a fragment-only string that points to a definition in the same file (e.g.
#MyType). [1]
Notes/rules:
- If the referenced definition is the file’s main definition, you can reference it by NSID without a fragment (e.g. com.example.record). Do not use a
#mainsuffix in $type fields. [1] - Refs may not point to token types. [1]
Example ref entries:
- External object type: { "type": "ref", "ref": "com.acme.defs#Address" }
- Local definition: { "type": "ref", "ref": "#Address" }
- Main definition reference (used in $type): "com.acme.person" (not "com.acme.person#main"). [1]
Source: AT Protocol Lexicon specification. [1]
🏁 Script executed:
# Check if pub.leaflet exists anywhere in the repo or if it's external
find . -type f -name "*.json" | xargs grep -l "leaflet\|pub\.leaflet" 2>/dev/null | head -10Repository: hypercerts-org/hypercerts-lexicon
Length of output: 183
🏁 Script executed:
# Look at existing strongRef definition to understand the pattern
cat -n lexicons/com/atproto/repo/strongRef.jsonRepository: hypercerts-org/hypercerts-lexicon
Length of output: 532
🏁 Script executed:
# Check how the README currently describes projectDescription to compare with review claim
sed -n '450,475p' README.mdRepository: hypercerts-org/hypercerts-lexicon
Length of output: 2492
🏁 Script executed:
# Check if there are any examples in the README showing how projectDescription should be used
sed -n '475,530p' README.mdRepository: hypercerts-org/hypercerts-lexicon
Length of output: 1661
🏁 Script executed:
# Search for any other direct definition references (not strongRef) to see if this is a pattern
rg '"ref":\s*"[^c]' lexicons/ | grep -v strongRef | grep -v "did" | head -20Repository: hypercerts-org/hypercerts-lexicon
Length of output: 525
🏁 Script executed:
# Check the full context around where projectDescription is used in examples
sed -n '475,510p' README.mdRepository: hypercerts-org/hypercerts-lexicon
Length of output: 1082
Fix projectDescription ref to match the strongRef pattern shown in README examples.
The schema uses "ref": "pub.leaflet.pages.linearDocument#main", but the README example shows projectDescription receiving a strongRef-shaped value ({ uri, cid }). This mismatch will cause validation failures when clients submit valid payloads matching the documented example. All other cross-record references in the codebase use com.atproto.repo.strongRef; this field should too.
Proposed fix
"projectDescription": {
"type": "ref",
- "ref": "pub.leaflet.pages.linearDocument#main",
- "description": "Rich-text description of this project, represented as a Leaflet linear document."
+ "ref": "com.atproto.repo.strongRef",
+ "description": "Strong reference to a Leaflet linear document describing this project. The referenced record must conform to pub.leaflet.pages.linearDocument#main."
},🤖 Prompt for AI Agents
In `@lexicons/org/hypercerts/claim/collection/project.json` around lines 25 - 29,
The projectDescription field currently points to
"pub.leaflet.pages.linearDocument#main" but should use the strongRef pattern so
clients submit the { uri, cid } shape shown in the README; update the
projectDescription schema to reference com.atproto.repo.strongRef (replace the
existing "ref": "pub.leaflet.pages.linearDocument#main") and keep or adjust the
description to indicate it stores a strongRef to the Leaflet linear document so
validation matches other cross-record refs (e.g., com.atproto.repo.strongRef)
used in the codebase.
- Replace activities array (activityWeight) with items array (strongRef) - Items can reference activities and/or other collections (recursive nesting) - Update collection description to reflect new structure - Update README with example showing recursive nesting - Update ERD to show items field and recursive relationship
- Delete org.hypercerts.claim.project lexicon - Create org.hypercerts.claim.collection.project sidecar - Move avatar and coverPhoto from collection to project sidecar - Projects are now collections + project sidecar (same TID) - Update README with project sidecar documentation and example - Update ERD to show collectionProject sidecar entity
58972d9 to
f1c6f28
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@README.md`:
- Line 467: Update the README entry for the `projectTitle` field so its
description reads "The title of this project" instead of "The title of this
collection"; locate the table row containing the `projectTitle` symbol and
change only the descriptive text to match the sidecar context while keeping the
rest of the constraints (maxLength: 800, maxGraphemes: 80) unchanged.
| | Property | Type | Required | Description | Comments | | ||
| | ------------------------- | -------- | -------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | ||
| | `projectTitle` | `string` | ❌ | The title of this project | maxLength: 800, maxGraphemes: 80 | | ||
| | `projectTitle` | `string` | ❌ | The title of this collection | maxLength: 800, maxGraphemes: 80 | |
There was a problem hiding this comment.
Minor: Correct the projectTitle description.
The description says "The title of this collection" but should say "The title of this project" to match the sidecar context.
📝 Suggested fix
-| `projectTitle` | `string` | ❌ | The title of this collection | maxLength: 800, maxGraphemes: 80 |
+| `projectTitle` | `string` | ❌ | The title of this project | maxLength: 800, maxGraphemes: 80 |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `projectTitle` | `string` | ❌ | The title of this collection | maxLength: 800, maxGraphemes: 80 | | |
| | `projectTitle` | `string` | ❌ | The title of this project | maxLength: 800, maxGraphemes: 80 | |
🤖 Prompt for AI Agents
In `@README.md` at line 467, Update the README entry for the `projectTitle` field
so its description reads "The title of this project" instead of "The title of
this collection"; locate the table row containing the `projectTitle` symbol and
change only the descriptive text to match the sidecar context while keeping the
rest of the constraints (maxLength: 800, maxGraphemes: 80) unchanged.
feat: Implement project as collection sidecar pattern
Overview
This PR refactors the project and collection lexicons to implement the "sidecar pattern" where projects are now represented as collections with an optional rich metadata sidecar. This change simplifies the data model while enabling more flexible organization through recursive collection nesting.
Key Changes
1. Project Sidecar Pattern (
org.hypercerts.claim.collection.project)org.hypercerts.claim.projectlexiconorg.hypercerts.claim.collection.projectas a sidecar record (shares same TID as collection)avatarandcoverPhotofrom base collection to project sidecarprojectTitleandshortProjectDescriptionfields2. Recursive Collection Nesting (
org.hypercerts.claim.collection)activitiesarray (withactivityWeightobjects) with simpleritemsarrayitemsnow accepts plainstrongRefto both activities AND other collectionstitle→collectionTitleshortDescription→shortCollectionDescriptioncollectionDescriptionfor full-text descriptionslocationreference toapp.certified.location3. Documentation Updates
Summary by CodeRabbit
New Features
Refactor
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.