My work (dark polling MVP)
GET /v1/me/my-work lists canonical visible asks, tasks and conversations for the
signed-in person. GET /v1/me/my-work/sync returns counts only. Project and category
access is rechecked for every request; Task-only people get assigned tasks only.
The org entitlement myWork.enabled defaults on. The platform switch defaults
false and must stay false until independent review and orchestrator promotion.
SSE integration waits on Operations; the page polls every 4 seconds visible and
30 seconds hidden, backs off to 60 seconds, and marks delayed data as stale.
Each blocked ask has one private home per project, person and bot. Its roster is
exactly the person and the dedicated service account, both plain members.
/o/<org>/chat/<conversation>?ask=<id> rechecks access before redirecting into the
asking thread. A person session replying to that root marks only that ask sent;
the ticket stays blocked until agent confirmation. No new nav or inline buttons
ship before the owner's Q-B decision.
The registered persona key reads /v1/orgs/<org>/my-work/open-asks?personId=<id>
through my_open_asks; empty plus incomplete never means nothing needed. The
registered key can post /v1/orgs/<org>/my-work/asks/<ask>/home. Admins register
the key and dedicated agent through /v1/orgs/<org>/my-work/settings. Human-minted
keys are refused and audited. Projection input comes from the protected
/v1/orgs/<org>/my-work/projection route. Follow-up shadow tickets are excluded
from all person-facing counts using the same followupRecordsForProjects helper as
Command Center. A registered followUpProjectId excludes the entire project;
without registration, a server-only creation stamp derived from API creation provenance AND the exact leading generated description
Follow-up fu-<12 lowercase hex> (docs/design/FOLLOWUP-STATE-GRAPH.md).
identify a shadow. PostgreSQL derives the stamp at insertion and preserves it on every update, including edits and API-key deletion. Session-created tickets and ordinary API-created tickets cannot become records through later description edits or forged fields. Migrations 10870/10880 recover the original API provenance and marker from an unedited row or its server-written first revision. Later description edits cannot change that classification, including edits made before migration. Missing original history keeps the ticket in ordinary counts. Polling reads only the boolean. Titles and mirror comments on adopted real tickets do not. Person digests are in agent_self only.
fgctl reconcile --my-work --apply requires the registered key. fgctl link is
dry-run by default and links an existing graph record to a canonical ask without
parsing titles. A stamp means re-project; a cleared stamp newer by database time
means adopt. The trigger covers due date as well as blocked fields. Escalated
asks remain blocked on the person; replies from escalated move to verifying.
- API reference:
GET /v1/openapi.json(paths appear only when the platform switch is on). - MCP tools: tool reference.
- Runbook: follow-up graph.
Questions are read from their durable question/root rows, with a separate ask ID per recipient. Unlocked decisions and unresolved task actions derive from their durable issue source. Ticket sources deduplicate by issue ID. Person reads refresh the canonical index without posting messages. A source without a posted conversation remains pending, with no fabricated deep link.
Drift notifications are durable and contain counts only. The page says the agent
was notified only after the registered open persona stream accepts the frame.
The event bridge consumes exact ask reply metadata only with an explicit local
orgs.<org>.myWork.enabled: true; its default is off. No bridge configuration is
changed here. The 60-second graph convergence check is an in-process fake-clock
check; the orchestrator must start the reconciler before promising ongoing sync.
A ticket's needsUserId makes it a task only while isBlocked is true.
Unblocked tickets remain tasks through assignment, current ownership, review,
an unresolved task action or an unlocked decision. waitingOnOthers includes
visible open tickets the viewer reported or is assigned to (including secondary
assignees) that are blocked on a different named person. Existing personal task members with an unknown (NULL) blocker retain their waiting entries. Existing personal
task membership, such as current ownership, also retains its waiting entries. Project/category scope
and archived/closed filtering apply before the list is built.
When graph, memory or told parity cannot be checked, the header keeps the canonical needs-you and unread counts and says “Could not check the agent's complete list”, even when asks are nonzero. A count never implies verified sync.
The All My Tasks and My Tasks sidebar counts (GET /v1/me/tasks) reuse the same follow-up classifier and visibility filters.