Assignee is who holds the work — an IAM username, or the login of the FIRST assignee when a forge issue has several. Absent when nobody holds it, which is exactly the state a claim needs.
DueAt is when the work is due, in unix seconds; absent means no due date. A forge row takes it from its MILESTONE's due date, since a forge issue has no deadline of its own. Never before StartAt, and never past 2200-01-01.
ExtRef anchors the item to something outside the todo — a mirrored issue ("github:owner/repo#123"), a pushed PR branch, or a record on another plane. It is the idempotency key the mirror upsert matches on. Absent when the item has no external origin.
ID is the work item's opaque handle, and it is NOT how you address it — ProjectKey plus Number is. Its shape says which source answered: a forge issue's is the forge's own numeric id in decimal, an index row's a minted "issue_" id.
Kind is what the item IS: issue, pr or epic. Set once at create and never changed, so a row does not migrate between surfaces. Deliberately not "task" — that word is the async plane (contract.go).
Labels are the item's remaining tags, with the status and priority labels lifted OUT — a column that stayed here would render twice, once as the card's column and once as a chip on the card. Always present; empty is [].
Number is the item's number ON ITS BOARD, from 1 and monotonic there — the forge's own issue number for a forge row, allocated inside the create transaction for an index row so it cannot race. Unique per board, never across the org.
Priority is urgent, high, medium, low or none. Also a label on a forge row. Never empty: "none" when nothing names one, so callers compare a value rather than test for absence.
ProjectKey is the board this item is on: the repository name for a forge issue, the index board's key otherwise. With Number it is the item's address in every other route.
Repo is the git repository the item is bound to, so a repository's Issues and PRs tabs are filters over this one table. Absent when the item is not repo-bound.
Source is which surface OPENED it: team, git, crm, helpdesk, cms or agent. Also set once. It is the ORIGIN, not the subject — source=helpdesk is an engineering issue opened from a support escalation, not a support ticket.
StartAt is when the work starts, in unix seconds; absent means unscheduled. A forge row takes it from when the issue was opened, but only once the issue has a due date — an interval needs both ends.
Status is the board column: backlog, todo, in_progress, done or canceled, and nothing else. On a forge row it is read off a LABEL, so relabelling in the forge web UI moves the card here and vice versa — and a CLOSED forge issue reads done whatever its labels say. Never empty: "backlog" when nothing names a column.