Problem
.agents/preferences.yaml stores configuration consumed by many agent skills, but its shape is undocumented as a machine-readable schema. Editors can't autocomplete or validate it, configs can drift from skill expectations silently, and the precondition for williamthorsen/configs.macos#12 (which depends on a published schema) cannot be met.
A second issue surfaced during design: repository.default_remote is currently a list, but only the first element is ever read. The shape was once intentional but has outlived its usefulness — the schema-writing exercise is the right time to normalize it.
Context
- Existing schemas in this package follow JSON Schema Draft 2020-12 (see
packages/agents/schemas/label-map.json).
- Skills reference preferences keys both inside the literal
.agents/preferences.yaml (10 sections) and beyond it (orchestration.*, artifacts.paths.*, merge.{strategy,delete_branch} reserved keys).
repository.default_remote is read at packages/agents/content/skills/get-session-context/SKILL.md:134 as default_remote[0].name — only index 0 is ever consumed.
- Other references in
~/ai-artifacts/ are historical run snapshots (frozen records) and do not require migration.
Solution
-
Write a JSON Schema at packages/agents/schemas/preferences.json (Draft 2020-12) describing every preferences key consumed by an installed skill or present in the repo's .agents/preferences.yaml. Top-level sections covered: artifacts, commit, editors, integrations, merge, orchestration, platform, pr, project, repository, ticket.
-
Strictness rules:
- Top-level:
additionalProperties: false (catches typos in section names).
- User-keyed inner maps (
integrations, orchestration.models, artifacts.paths): additionalProperties constrains the value shape but permits any key name.
- Reserved-but-not-honored keys (
merge.strategy, merge.delete_branch): documented as such in description text; not flagged with deprecated.
-
Required vs optional:
- Top-level:
required: []. A fully empty preferences file is valid.
- Sub-fields: required when their absence would make the parent object meaningless (e.g.,
editors[].name, editors[].command, repository.default_remote.name, integrations.<name>.enabled, format-string fields when their parent section is present).
-
Normalize repository.default_remote from a single-element list to a singular object across:
.agents/preferences.yaml
packages/agents/content/skills/get-session-context/SKILL.md
packages/agents/README.md (property table + example)
- The new schema describes the singular shape only.
-
Test coverage in packages/agents/:
- Schema is well-formed (loads as valid JSON Schema).
- The live
.agents/preferences.yaml validates against the schema (guards against drift).
-
Out of scope:
- Runtime CLI schema validation (e.g.,
codeassembly-agents validate-prefs).
- Editor
$schema linking conventions in .agents/preferences.yaml.
- Multi-remote awareness in the schema (would be a separate, additive change with a different shape).
Acceptance criteria
Problem
.agents/preferences.yamlstores configuration consumed by many agent skills, but its shape is undocumented as a machine-readable schema. Editors can't autocomplete or validate it, configs can drift from skill expectations silently, and the precondition for williamthorsen/configs.macos#12 (which depends on a published schema) cannot be met.A second issue surfaced during design:
repository.default_remoteis currently a list, but only the first element is ever read. The shape was once intentional but has outlived its usefulness — the schema-writing exercise is the right time to normalize it.Context
packages/agents/schemas/label-map.json)..agents/preferences.yaml(10 sections) and beyond it (orchestration.*,artifacts.paths.*,merge.{strategy,delete_branch}reserved keys).repository.default_remoteis read atpackages/agents/content/skills/get-session-context/SKILL.md:134asdefault_remote[0].name— only index 0 is ever consumed.~/ai-artifacts/are historical run snapshots (frozen records) and do not require migration.Solution
Write a JSON Schema at
packages/agents/schemas/preferences.json(Draft 2020-12) describing every preferences key consumed by an installed skill or present in the repo's.agents/preferences.yaml. Top-level sections covered:artifacts,commit,editors,integrations,merge,orchestration,platform,pr,project,repository,ticket.Strictness rules:
additionalProperties: false(catches typos in section names).integrations,orchestration.models,artifacts.paths):additionalPropertiesconstrains the value shape but permits any key name.merge.strategy,merge.delete_branch): documented as such indescriptiontext; not flagged withdeprecated.Required vs optional:
required: []. A fully empty preferences file is valid.editors[].name,editors[].command,repository.default_remote.name,integrations.<name>.enabled, format-string fields when their parent section is present).Normalize
repository.default_remotefrom a single-element list to a singular object across:.agents/preferences.yamlpackages/agents/content/skills/get-session-context/SKILL.mdpackages/agents/README.md(property table + example)Test coverage in
packages/agents/:.agents/preferences.yamlvalidates against the schema (guards against drift).Out of scope:
codeassembly-agents validate-prefs).$schemalinking conventions in.agents/preferences.yaml.Acceptance criteria
packages/agents/schemas/preferences.jsonexists, uses JSON Schema Draft 2020-12, has the same$idpattern aslabel-map.json, and covers all top-level sections enumerated above.additionalProperties: false; user-keyed inner maps (integrations,orchestration.models,artifacts.paths) permit additional keys with constrained value shapes.requiredis[]; sub-required lists are present where described above.repository.default_remoteis a singular object in.agents/preferences.yaml, inget-session-context/SKILL.md, and inpackages/agents/README.md. No remaining references todefault_remote[0]ordefault_remote[].*in this repo..agents/preferences.yamlvalidates against it.packages/agents/README.mdreflects the singulardefault_remoteshape in both the property table and the example.