Skip to content
NeuroDock

0004 — Profile schema design

Source: docs/decisions/0004-profile-schema-design.md is 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

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.

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.
  • 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 init scaffolds 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.
  • identity is 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.
  • audhd is a first-class identity, not a derived ["adhd", "asd"]. The lived experience differs.

The full ADR carries three open questions:

  1. How does extends: resolve when the named preset is unavailable? (Recommended: warn-and-use-defaults.)
  2. How are schema version mismatches surfaced? (Recommended: one-line stderr notice on first load per session.)
  3. Should display_name default from $USER at neurodock init time? (Recommended: yes — friction reduction.)