0004 — Profile schema design
Source:
docs/decisions/0004-profile-schema-design.mdis the canonical artefact. This page is a short summary; read the full ADR for the four alternatives considered and the seventeen binding design decisions.
- Status: Accepted
- Date: 2026-05-15
- Deciders: Thomas Lennon (maintainer),
mcp-architect
Context
Section titled “Context”The profile at ~/.neurodock/profile.yaml is read by every MCP server, every skill, the CLI installer, and the preset bundles in profiles/. Three properties make it unusually load-bearing: cross-cutting across Python and TypeScript packages, consent-bearing for three independent gates (embeddings, telemetry, os_idle_consent), and forward-evolving as features land each quarter.
Decision
Section titled “Decision”Adopt nested YAML with permissive forward-compat (additionalProperties: true at every nesting level). Loaders accept unknown keys, preserve them on round-trip, and validate known keys strictly. A separate neurodock profile validate CLI command surfaces typos.
View alternative approaches and technical debates
Alternatives rejected:
- Flat TOML config — ecosystem precedent is YAML; TOML’s strict typing works against forward-compat.
- Nested YAML with strict schema — breaks every quarter when a new field lands; downgrades silently lose data.
- Per-skill configs — fragments consent across N files; defeats the “Claude that knows me” experience.
Cross-cutting rules established here
Section titled “Cross-cutting rules established here”- Forward compatibility is the central correctness property. A v0.1 loader reading a v0.2 profile must preserve unknown keys on round-trip.
- Defaults are loader-applied, not file-written.
neurodock initscaffolds a minimal profile; the loader fills defaults at read time. - Lived-experience-led defaults.
motion: reduced,output_format: answer_first,embeddings: local,telemetry: off,os_idle_consent: false— all chosen because they are the safer ND-friendly value. - No PII surface. Email, real name, date of birth do not exist in the schema. Contributors who try to add them face an ADR-level conversation.
identityis the only required block. Every other block is optional; defaults apply.extends:for preset composition. Single-level only in v0.1; deep chaining deferred to a future RFC.audhdis a first-class identity, not a derived["adhd", "asd"]. The lived experience differs.
Open questions
Section titled “Open questions”The full ADR carries three open questions:
- How does
extends:resolve when the named preset is unavailable? (Recommended: warn-and-use-defaults.) - How are schema version mismatches surfaced? (Recommended: one-line stderr notice on first load per session.)
- Should
display_namedefault from$USERatneurodock inittime? (Recommended: yes — friction reduction.)
What’s next
Section titled “What’s next”- Read the full ADR.
- See the profile schema reference.
- See the profile concept page for the higher-level picture.