ADR-020: Self-identity: capture once globally, seed the self person per workspace
Date: 2026-06-05 Status: Accepted Author: Rômulo Febasi
Context
The Synapse self: true person is load-bearing: syn identity export, syn cv export and syn experience all locate exactly one self person and refuse to run
otherwise. Yet through v0.5 there was no way to set the flag: the user had to
hand-edit YAML to make any of those features work. Onboarding also left identity
implicit: syn setup only captured locale and output format.
The v0.6 headline is to close that gap and make the tool know its owner: capture name, birthdate, profession and employers, and have every workspace carry a canonical self person derived from that. Three forces shape the design:
- One owner, many workspaces. The identity is a property of the human, not of any single workspace. Capturing it per workspace would force re-entry and risk drift between copies.
- CI/agents must never block.
syn initruns in pipes, scripts and agent loops. Making setup compulsory cannot introduce a path that waits on stdin (BR-14.1, the hard invariant inherited from SYN-187--no-input). - One stable shape.
core, MCP context, cv export and federation must depend on a single self-person schema, not each re-deriving fields ad hoc.
Decision
Capture once, seed everywhere. The self-profile (name, optional birthdate,
optional headline, optional employers) is captured a single time during syn setup
and persisted to a global profile.toml, kept separate from config.toml
(config describes tool behaviour and cascades; the profile describes the human and
does not). On syn init, Synapse materialises/refreshes the canonical self: true
person from that profile.
- Compulsory setup (SYN-170):
syn initrequires a global config. Absent + TTY runs the guided setup inline; absent + non-TTY falls through on defaults without writing or blocking. - Canonical schema (SYN-173, BR-14.3):
self: true,birthdate(ISO 8601),headline(consumed by cv),affiliations[] = { org, role? }.affiliationsis deliberately distinct frommemberships(BR-4.4 reserves the latter for person→project). Employers materialise asentity(kind=org). - Idempotent seed (SYN-172, BR-14.4): reuse the existing self id (slug never
churns), preserve
created/memberships/body on refresh, guarantee exactly one self, and skip BR-13 enrichment so seeding never forces a model download.
SYNAPSE_PROFILE overrides the profile path (tests pin it to keep workspaces
hermetic; advanced users can point at an alternate profile).
Consequences
- Better.
identity/cv/experiencework out of the box after onboarding. The assistant gains the owner’s name/role/employers for routing and federation context. Identity is entered once and propagates to every workspace. - Worse. A second global file (
profile.toml) to reason about alongsideconfig.tomland the registry. The seed adds work toinit’s hot path (bounded: one person + N org entities, no enrichment). - Open. Rich person→org graph edges are deferred: v0.6 records affiliations in
frontmatter and materialises org entities but does not wire a typed membership
link. Birthdate validation is a lenient
YYYY-MM-DDshape check, not a full calendar. Revisit both if/when employer-scoped project organisation lands.
Alternatives considered
- Store identity inside
config.toml. Rejected: conflates tool behaviour (which cascades system → global → workspace) with personal identity (exactly one, global, no cascade). Mixing them muddies precedence and federation redaction. - Capture per workspace. Rejected: forces re-entry, invites drift between copies, and contradicts “the identity is the human’s, not the workspace’s”.
- Persist a global config on non-TTY init. Rejected: writing files from CI/pipe runs is a side effect, and the silent-default fallback (BR-14.1) only requires behaving as defaults, not materialising them.
- Reuse
membershipsfor employers. Rejected: BR-4.4 reservesmembershipsfor person→project;collect_links/cv export already assume aprojectkey. A separateaffiliationsfield keeps both semantics clean. - Run BR-13 enrichment during seed. Rejected:
initruns before the semantic models may exist; embedding the self person then would force a ~920 MB download or fail. The self person embeds on its next edit orsyn reindex.