Repository navigation
feat(framework): resolve one person across tools and machines #661
Description
Activity
- added a parent issue
on Aug 15, 2026 Scope grown by the decision of 2026-08-16
Both modes are supported, so this issue no longer only reconciles identities — it owns the mapping that switches between them.
- Records always carry a pseudonym. This issue produces it, and guarantees it is stable for one person across tools and machines.
- The pseudonym-to-person mapping is a separate artefact, outside the repository, access-controlled. Its presence is what makes a deployment named; its absence is what makes it anonymous.
- Resolution across the four vendor identities stays as specified. Copilot's is pseudonymous at the source, so it cannot be matched by address and needs the mapping or stays unresolved.
Two properties to add, both consequences of serving two modes from one format:
- Removing the mapping must anonymise every future reading, immediately, without touching stored records.
- The mapping must be auditable: given a report line, one can see which raw identities produced it — and that audit must itself be gated, or it becomes a way around the anonymous mode.
- added a commit that references this issue
on Aug 24, 2026 Moved to the front
A product decision taken 2026-08-28 makes this the pivot of the whole aggregation milestone.
The line between what the local layer answers and what a hosted product answers is not a pricing choice, it is a structural one: a machine holds one person's files. Everything about your own work — tokens, models, steps, tasks — is answerable locally and should stay that way. Nothing about a second person is, and no amount of local cleverness changes it.
That makes this issue the one thing that is simultaneously indispensable to any team view and impossible to fake locally. Per person, per team, per epic (#656), the task breakdown (#720), and the backlog join (#649) are all views; they need their key first, and this is the key.
Practical consequence: it moves ahead of #654, which is a lookup table that opens nothing and can land at any time.
One constraint worth carrying into the design, from the layer's existing shape:
person_idis opted into per person on the local-read route and is deliberately not derived from any tool's own user attribute —telemetry-sink-record.tsexcludesuser.idon purpose, since an export carries it whenever the tool happens to set it, consent or not. Resolving one person across tools and machines must keep that property: an identity is something a person grants, never something a join infers.- added 9 commits that reference this issue
on Aug 28, 2026
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Projects
- StatusShow more project fieldsDone
As a team lead reading a report
I want one person to appear as one person, whatever tool they used
So that a weekly figure is a fact rather than an artefact of how many tools someone happens to run
Acceptance
Why this is not trivial
Measured: the same human carries a different identifier per tool, and none of them is the git identity that appears in commits.
user.email,user.account_uuid,user.account_id,user.id,organization.iduser.email,account_iduser_emailin the hook payloadenduser.pseudo.id, described as pseudonymousCopilot's is pseudonymous by construction, so it cannot be reconciled by matching an address — it needs a mapping someone maintains, or it stays unresolved. Nothing in the design produces an actor attribute of its own: the run record has no author field at all.
"Team" has the same problem one level up: it is named in #656's output and defined nowhere, with no source of truth.
Out of scope
Relations