Community Annotation — UI Reference + Troubleshooting#
This page is a button-by-button reference for the Community Annotation UI, plus a deep troubleshooting catalog for both annotators and authors.
If you want the guided flow first:
Annotators: Community Annotation — Annotator Guide (UI + Voting)
Authors: Community Annotation — Author Guide (Repo Setup + Operations)
Every screen in order, with pictures: Lifecycle Walkthrough (Screens, Step by Step)
“GitHub sync” Modal (Repo Discovery + Pull/Publish)#
Open it from the Community annotation accordion.
This modal is a 4-step wizard:
1) Sign in#
Button: Continue with GitHub
Notes:
This uses a GitHub App OAuth flow (no token paste).
The token expires after 8 hours and is stored only in this tab’s
sessionStorage(closing the tab signs you out; a reload does not). Disconnect GitHub (the icon beside GitHub in this dialog) revokes it at GitHub and disconnects this dataset’s repository too; if GitHub cannot be reached, a notification says the token stays valid until it expires.A token GitHub refuses (it expired or was revoked elsewhere) signs you out here with one line: “Your GitHub sign-in expired or was revoked. Sign in again to Pull or Publish; your unpublished changes stay in this browser.” The repository connection is kept: signing in again as the same GitHub user connects it again, with your unpublished changes.
Step 1 of 4. The four step names stay visible down the left, and the header tracks the dataset, the GitHub identity, and the bound repository throughout.#
2) Install app#
Buttons:
Add repo (opens GitHub App installation flow)
Reload (refresh repo list after installing)
If your annotation repo does not appear later, this step is the usual cause.
Step 2 of 4. The status line always states the exact count and page, because an organisation can expose thousands of repositories.#
3) Choose repository#
Filter input: Filter repositories…
Repos are shown as cards (public/private).
Select a repo card, then use the wizard navigation button Connect.
If replacing an existing repository, the same button reads Switch repo.
The empty filter result on step 3. No repositories match this filter. is a
filter outcome, not a permission problem — clear the filter to see the full
list.#
What “connect” means:
the repo choice is saved locally per dataset and per GitHub account
Cellucid validates required paths:
annotations/config.jsonannotations/config.schema.jsonannotations/schema.jsonannotations/moderation/merges.schema.jsonannotations/users/
the three schema files must be exactly the cellucid-annotation template’s, which Cellucid checks by their Git blob ids without downloading them; a schema that differs stops the Pull with a message naming the file to copy again
4) Sync#
Buttons:
Pull latest
Publish
Optional:
Auto pull toggle
interval selector (10/15/60 minutes)
Navigation:
Back / Next buttons navigate the wizard.
A status line at the bottom shows progress, warnings, and error text.
While any sync is running — including a background Auto pull — Pull
latest and Publish are disabled until it finishes. A Pull or Publish that
still reaches a running sync does not run and reports Another GitHub sync is still running. Wait for it to finish, then try again.; one you cancel reports
Cancelled.. Only a completed transaction reports its success text.
Step 4 of 4 after a successful Pull latest. The status line under the buttons is where every outcome is reported verbatim.#
The same panel after Publish. Published. means GitHub accepted the write
to the repository. When you cannot write to the repository, Publish opens (or
updates) a pull request instead and says Opened a pull request: <link>. The repository has your changes once its authors merge it.; nothing new to write
says Nothing new to publish: GitHub already has your changes.#
What Pull does (technical)#
Pull:
reads the repository at one commit: the branch’s commit and the listings of
annotations/andannotations/moderation/come in one request, and everything after is read by Git object id from that commit, so one Pull never mixes two commitsstops there when nothing under
annotations/changed since your last completed Pull (one or two requests in all)checks the three schemas by blob id, reads
annotations/config.jsonand listsannotations/users/by its tree iddownloads only the user files (and the optional
annotations/moderation/merges.json; only authors may publish changes to that document) whose blob id changed, many files per requestvalidates each file as it arrives and keeps it in the required persistent IndexedDB cache, batch by batch, so an interrupted Pull resumes where it stopped; Cellucid never switches to an in-memory cache
compiles the merged view in the browser
applies author settings from
annotations/config.json(annotatable columns, thresholds, closed fields)
One file never stops a Pull. A user file or merges file that is not valid is
left out of the consensus on its own and reported in one warning (how many
files, with each file and its reason under its details); a path under
annotations/users/ that is not a ghid_<id>.json file, or a case variant of
a layout path, is ignored and listed the same way. A missing configured
categorical field, an invalid annotations/config.json, a schema that is not
the template’s, or a users listing GitHub reports as truncated fails the
complete Pull without changing annotation state. There is no limit on how many
user files a repository holds or on their total size: changed files are cached
a batch at a time, and the merged view is compiled by streaming the cache one
file at a time. Cellucid checks configured fields before selecting the
raw-cache scope or downloading user/moderation files, so that mismatch cannot
mutate the raw-file cache.
Requests are paced by the request budget GitHub reports; when GitHub names a wait, the progress notification says so. A request is never cut by a fixed time limit: only a connection on which nothing arrives at all is given up and asked again.
What Publish does (technical)#
Publish always writes your user file, with every change of yours not published yet:
annotations/users/ghid_<id>.json
If you are an author, Publish may also update:
annotations/config.jsonannotations/moderation/merges.json
Publishing modes:
Direct push if GitHub reports you can push.
Fork + Pull Request if you cannot push but the repo allows forking. You make the fork on GitHub (Cellucid never creates one) and install the Cellucid GitHub App on your account with access to it (All repositories, or Only select repositories with the fork selected).
Cellucid chooses one route from current permissions before publishing. If that route fails, the failure is reported; a different route is not substituted.
With Fork + Pull Request, you have one pull request per base branch, from
the head branch cellucid-annotations/ghid_<id>/… in your fork. Every Publish
resets that branch to the base branch’s current tip and writes your whole user
file on it (every dataset you annotate there, the open pull request’s pending
sections included), so the pull request’s diff is your one file and an earlier
squash-merged pull request never makes it conflict. An open pull request is
reused. An agent’s vote or suggestion, published alone, is added to the file
the open pull request already proposes, so it never drops that pull request’s
other changes.
If the connection drops while a write is under way, GitHub may or may not
have it: Cellucid says GitHub may already have applied this change; Cellucid pulls now to see. and pulls at once, so what it knows of your file is
GitHub’s again before the next Publish. Stop on an agent’s vote while it
is written works the same way (see Agents below).
Common publish pitfalls:
branch protection blocks direct pushes,
forking disabled blocks PR flow,
no fork yet: Publish says
You have no fork of <owner>/<repo> yet: fork it on GitHub, then Publish again.under the sync line, with a Fork on GitHub link,a fork GitHub is still copying:
GitHub is still copying your fork …; Publish again in a minute.,a fork the app cannot write to:
Cellucid cannot write to your fork …, with an Install the app link (install it on your account with access to the fork).
Profile (Optional) and “Your identity” Modal#
In the Community annotation accordion, you will see the optional Profile block.
Buttons:
Edit: opens the “Your identity” modal
Clear: clears local profile fields (you still need to Publish to update GitHub)
The “Your identity” modal includes:
Name: free text used to search ORCID (e.g. “Alice Smith”)
Affiliation / role: free text (e.g. “Theis Lab, Postdoc”)
LinkedIn: handle only (no URL; lowercase
a-z0-9-)ORCID: accepts a checksum-valid ORCID iD and auto-suggests matches
Save / Cancel
Notes:
These fields are optional and are written to your GitHub user file only on Publish.
Annotation repo validation disallows email fields (privacy).
For eligible exact input with no surrounding whitespace (of any length), typing at least three Unicode code points in either Name or ORCID starts a 250 ms-debounced direct browser request to
https://pub.orcid.org, unless the exact query is served from the 60-second per-modal cache. An exact ORCID iD uses/v3.0/{id}/person; other text uses/v3.0/expanded-search/with at most eight results. The request omits credentials and referrer information, but the typed text still leaves Cellucid and is visible to ORCID and the network path.Save accepts an empty ORCID or an exact checksum-valid ORCID iD. The name text is search input, not a valid saved ORCID iD.
Consensus column (optional)#
Collapsible title: Consensus column
This section builds a local categorical obs column for visualization:
Dropdown: Annotatable column
Input: New column key
Settings:
Consensus threshold
Min annotators
Button: Build derived column
For each built column whose consensus changed since (a Pull, a vote): one line
<column>: consensus changed since built (N categories)with Rebuild
The key starts as community_<column> and the settings at the column’s rule
in the repository. This does not publish anything; it is a local view helper
and a step of the history that records its outcomes, rule and source, and
replays by name (Community Annotation — Author Guide (Repo Setup + Operations), section 11).
Consensus snapshot + local cache#
Collapsible title: Snapshot and cache
Consensus snapshot#
Button: Download (its tooltip reads
Download cellucid-consensus.json)
Downloads a locally built cellucid-consensus.json snapshot (not written back
to GitHub). Pull first when the export must include the newest shared files.
The snapshot contains:
suggestions: merged suggestions per bucket (withupvotesanddownvoteslists)consensus: per-bucketstatus/label/confidence/voters/netVotes/suggestionId
Local cache (two clears, different meanings)#
Two different clears exist (they do different things):
Clear session
clears local votes/suggestions/comments and annotatable-column selections for the current dataset/repo/branch scope
does not touch GitHub
use this if your local state is confused and you want to start fresh
risk: you can lose unpublished work
Clear downloads
clears what Pull keeps from GitHub for this scope: the open dataset’s part of each file read from
annotations/users/*andannotations/moderation/merges.json, the reasons files were left out, and the record of the last completed Pull; the next Pull reads everything againuse this if Pull behavior seems wrong due to a corrupted cache
safe: does not remove your local votes/suggestions/comments
The annotation “session” above is separate from Cellucid’s portable
.cellucid-session files. Community Annotation is intentionally excluded from
the session files Share… and Load… handle. GitHub tokens remain tab-scoped in
sessionStorage and expire after 8 hours; annotation intent and pulled-file caches retain their own
dataset/repo/branch/user scope. See
What gets saved and restored.
Voting Modal (Per Category)#
You open this by clicking a category label in the categorical legend when the selected field is annotatable.
The voting modal for one category: the status line, the suggestion cards, and the New suggestion form beneath them.#
What you see at a glance#
A consensus status line (Consensus / Disputed / Pending)
A list of suggestion cards
A New suggestion form
The status line is exact about which of the three states applies and why:
State |
Status line |
When |
|---|---|---|
Consensus |
|
at least |
Disputed |
|
enough voters, but the leader is tied or confidence is below threshold |
Pending |
|
fewer than |
Disputed by a tie. Both suggestions have identical net votes and identical upvote counts, so neither leads. A tie is disputed regardless of confidence, and the banner names every tied label alphabetically.#
Pending. One voter against a three-annotator minimum. No confidence figure is reported, because the column’s own rule says there is not yet enough participation to compute one.#
Suggestion card anatomy#
One card, with every element named below present: label, net score, the three
evidence rows, the vote buttons, the owner-only actions, the attribution line,
and the comment box with its character counter.#
Each suggestion card shows:
label (the proposed annotation)
net …score (up - down)Ontology: value or
—Markers: summary or
—Evidence: preview (with View full evidence if long)
vote buttons:
▲
▼
Vote toggling:
click ▲ or ▼ to vote
click the same arrow again to clear your vote
Duplicates:
suggestions with exactly the same label (compared after Unicode NFC normalization; case, spacing and punctuation are not folded) are one suggestion: the earliest proposal is shown, and each person’s votes across them count once (their majority; a tie is no vote)
adding a suggestion, or renaming one, to a label already shown in the category is refused
labels that differ (
T cellandT-cell) can split votes until an author merges them
Merged bundles (author moderation):
a merged suggestion shows a “Merged bundle …” row and a View merged button; any author can detach a member there, but only the GitHub identity that created the merge record can edit or delete its note
bundle totals are de-duplicated to one effective vote per user
a direct vote on the merged target wins; otherwise Cellucid delegates the majority of that user’s votes across the merged members, with a tie producing no effective vote
an author merges a suggestion into another by dragging its card onto the other, or from the keyboard with the card’s Merge… button: choose the target suggestion, add an optional note, and confirm
Comments:
the annotation contract sets no length limit on comments, labels, evidence or any other text; only the contributor’s whole file is bounded (1,000,000 UTF-8 bytes)
Enter submits a comment
Shift+Enter inserts a newline without submitting
unsent comments and suggestions, and open edits of your own comments, suggestions, and merge notes, keep their text, cursor, and focus when the modal refreshes (a Pull, a change from another tab, your own vote)
if the item you were editing is deleted, merged away, or no longer on the page you are viewing, or voting closes, the editor closes and warns
Edit not saved: the … you were editing is no longer shown here (deleted, merged, closed, or on another page).
Renamed columns and categories#
A column or category you renamed in this browser (the field toolbar, the
legend, a history step) keeps its dataset name in the repository: votes,
suggestions and the consensus are filed under the dataset’s names, so other
people see them, and a rename (or a history jump, a session or the autosave
that brings one back) never moves anything in the repository. The legend and
the voting dialog show your name; the dialog’s header adds the repository’s
(Alpha renamed (in the repository: cell_type • alpha)). While a column is
open for voting, it cannot be renamed or edited, whatever name it shows.
Agents and community annotation#
An agent (the chat bar, Claude or ChatGPT through the connector, a local app
through cellucid mcp) and a Python or R notebook can read the community
annotation of the dataset shown and vote, through the same session as the
voting dialog. Connecting a repository and signing in to GitHub stay yours.
Reading (annotation_suggestions, no permission needed): for each
category of a column, its suggestions (label, ontology term, who suggested it
as the dialog names them, votes, your own vote, and whether it is delegated
from votes on merged suggestions) and its consensus (status, leading label,
voters) under the repository’s settings, plus when this browser last pulled.
Columns and categories are named as you see them. A large column comes in
pages, each whole (next starts the following one). What the agent reads
goes to its provider, other people’s GitHub logins and names included
(AI agents: what they are sent).
Voting (annotation_vote) publishes that one vote and nothing else:
you are asked first (Publishing is Ask by default), whoever asks: the question names the vote (“vote “Alpha cell” up for alpha”), the repository it goes to (or that it opens a pull request when you cannot write to the repository), and how many of your other changes stay unpublished;
only your file as GitHub holds it plus this vote is written: your drafts, your other votes not yet published and, for an author, the repository settings and merges are not published (they wait for your own Publish);
a vote that is already so (published and here) asks nothing and writes nothing;
an agent’s vote never opens a dialog (your profile’s fields are optional; the file is named by your GitHub login), waits for a Pull under way, and pulls first when your file changed on GitHub since the last Pull;
a suggestion is named by its id or its label; suggestions with the same label are one suggestion (the earliest proposal), so a label names one;
the agent is told where the vote went: the repository, a pull request (with its link), or nowhere (it was already so).
Undo turn cannot take back a published vote. The agent’s line counts what it published (“1 vote published, not undoable”), the turn keeps the vote in its record in the history, and Undo turn says the vote stays published. Change it back by voting again.
Stop while a vote is written: if GitHub may already have it, Cellucid pulls at once and the agent is told what the Pull shows: published, or kept in this browser and not published. Your next Publish works either way.
Troubleshooting (Massive)#
This section is organized by “what you’re trying to do”. Always start by confirming your scope:
dataset id (status panel)
owner/repo@branchGitHub login
Troubleshooting — Annotators#
“Another browser tab/window is already connected…”#
Cause: Cellucid may enforce a single active tab per scope (dataset + repo@branch + GitHub user id) to prevent silent data loss.
Fix:
close the other Cellucid tab/window for the same scope, then retry
if you can’t find it, close all other tabs for this origin and reopen one tab
I can’t publish (and I’m not allowed to fork)#
Cause: you have no push permission and the repo has
allow_forkingdisabled.Fix: ask the author to enable forking or grant write access.
Fork + PR publish fails#
“You have no fork of …”: fork the repository on GitHub (the Fork on GitHub link), then Publish again.
“Cellucid cannot write to your fork …”: the app is not installed on your account with access to the fork. Install it (Install the app; All repositories, or Only select repositories with the fork selected), then Publish again.
“GitHub is still copying your fork …”: Publish again in a minute.
“Remote user file changed since your last Pull” on Publish#
Cause: your user file on GitHub is newer than the one your last Pull read (common if you published from another device).
Fix: Pull latest, confirm your intended state, then Publish again. There is no option to overwrite: Cellucid never replaces a remote file it has not read.
“Your published file … is not a valid annotation file”#
Cause: your own file on GitHub fails the annotation contract (for example a file written for the earlier, version-2 contract). Pull leaves it out, and Publish will not overwrite it.
Fix: fix or remove the file on GitHub (or ask an author to), then Pull and Publish again.
An agent’s vote does this itself: it pulls, then publishes the vote on the file as it is now.
Pull succeeds but I don’t see new votes#
Checklist:
confirm you’re on the same
owner/repo@branchas the rest of the groupconfirm the author did not close the column (🗳️🏁)
confirm you’re clicking the correct category in the correct column
confirm the other person actually Published (or their PR merged)