Origin: node-monorepo-tools#355 (work-types alignment + drift detection)
Problem
packages/agents/content/skills/_data/work-types.md is the canonical work-types reference for skill consumers, but its markdown-table shape is hard to consume programmatically:
- Downstream repos (e.g.,
node-monorepo-tools) need to derive constants like DEFAULT_WORK_TYPES from it. Markdown table parsing is brittle.
- Drift detection between repos requires byte-level or semantic comparison. Markdown formatting (whitespace, alignment) introduces noise that obscures real semantic drift.
- The current document mixes structural data (work-type rows) with prose (precedence rule, breaking-change rule, AI-instructions carve-out). The two have different lifecycles and consumers.
node-monorepo-tools#355 establishes a structured-data SSOT (packages/release-kit/src/work-types.json) for the release-kit package and adds a release-kit work-types check command that fetches upstream and asserts equivalence. Until codeassembly publishes a matching JSON file, the check runs in tolerant mode (warn on 404 → exit 0). This ticket lands the upstream JSON so the check can flip to blocking.
Context
node-monorepo-tools#355 is still pending; this ticket is no longer bound by its prior schema decisions. Any agreed shape here will be reflected in that repo before it lands.
- The current
work-types.md carries 11 types in PRIMARY/SECONDARY/TERTIARY tiers. The new JSON adopts a 15-type vocabulary (adds drop, deprecate, sec, perf) in public/internal/process tiers, aligned with conventional changelog ecosystems.
- The schema validation precedent in this repo is
packages/agents/schemas/preferences.json + packages/agents/src/lib/__tests__/preferences-schema.test.ts. The new schema and test mirror that pattern.
- The install command's
_data/ copy already ships any file regardless of extension; no install-code change is required for the JSON to land in ~/.claude/skills/_data/.
Solution
Data shape
packages/agents/content/skills/_data/work-types.json carries the canonical taxonomy with this per-type record shape:
{
"key": "feat",
"aliases": ["feature"],
"tier": "public",
"emoji": "🎉",
"label": "Features",
"breakingPolicy": "optional"
}
emoji and label are separate fields (not a combined header). Consumers needing a pre-rendered string concatenate them. The 15 types in canonical render order: feat, drop, deprecate, fix, sec, perf, internal, refactor, tests, tooling, ci, deps, ai, docs, fmt. fmt carries excludedFromChangelog: true.
Schema
packages/agents/schemas/work-types.schema.json is a JSON Schema (draft 2020-12) with additionalProperties: false everywhere. It enforces:
- Top-level:
version (semver), tiers (the three-element array ["public", "internal", "process"]), types (array)
types[].key: lowercase pattern ^[a-z][a-z0-9-]*$
types[].tier: must be one of the values in the top-level tiers
types[].emoji: non-empty string
types[].label: non-empty string
types[].breakingPolicy: enum of forbidden | optional | required
types[].excludedFromChangelog: optional boolean
Cross-element uniqueness (unique key values, globally unique aliases) is asserted in the validation test, not the schema (JSON Schema can't express it cleanly).
Markdown removal
packages/agents/content/skills/_data/work-types.md is deleted. Its prose content (precedence rule, breaking-change rule, AI-instructions carve-out) moves into commit/SKILL.md, which is the only skill that consumes those rules. The structural data lives only in work-types.json.
Skill prose updates
commit/SKILL.md "Work types reference" section is rewritten to:
- Group types by the new tiers (public/internal/process)
- State the precedence rule using tier ordering
- State the breaking-change rule using each type's
breakingPolicy field (replacing the legacy "PRIMARY only" rule)
- Carry the AI-instructions carve-out
summarize-change/SKILL.md updates:
- Link target:
[work-types.md](../_data/work-types.md) → [work-types.json](../_data/work-types.json)
- Priority phrase:
Primary → Secondary → Tertiary → public → internal → process
Sync mechanism
codeassembly-agents install continues to copy _data/ whole into ~/.claude/skills/_data/. The new work-types.json ships automatically. node-monorepo-tools fetches it via the raw.githubusercontent.com URL pattern in its release-kit work-types check command.
Acceptance criteria
Coordination notes
- The schema in this repo is canonical.
node-monorepo-tools fetches it via the raw.githubusercontent.com URL pattern. If the schema evolves, both repos update in lockstep.
- Order of
types[] is canonical render order. Asserted by the schema validation test.
- The breaking-change rule is now per-type (
breakingPolicy field), not tier-level. Both repos must reflect this.
Origin: node-monorepo-tools#355 (work-types alignment + drift detection)
Problem
packages/agents/content/skills/_data/work-types.mdis the canonical work-types reference for skill consumers, but its markdown-table shape is hard to consume programmatically:node-monorepo-tools) need to derive constants likeDEFAULT_WORK_TYPESfrom it. Markdown table parsing is brittle.node-monorepo-tools#355establishes a structured-data SSOT (packages/release-kit/src/work-types.json) for the release-kit package and adds arelease-kit work-types checkcommand that fetches upstream and asserts equivalence. Until codeassembly publishes a matching JSON file, the check runs in tolerant mode (warn on 404 → exit 0). This ticket lands the upstream JSON so the check can flip to blocking.Context
node-monorepo-tools#355is still pending; this ticket is no longer bound by its prior schema decisions. Any agreed shape here will be reflected in that repo before it lands.work-types.mdcarries 11 types in PRIMARY/SECONDARY/TERTIARY tiers. The new JSON adopts a 15-type vocabulary (addsdrop,deprecate,sec,perf) inpublic/internal/processtiers, aligned with conventional changelog ecosystems.packages/agents/schemas/preferences.json+packages/agents/src/lib/__tests__/preferences-schema.test.ts. The new schema and test mirror that pattern._data/copy already ships any file regardless of extension; no install-code change is required for the JSON to land in~/.claude/skills/_data/.Solution
Data shape
packages/agents/content/skills/_data/work-types.jsoncarries the canonical taxonomy with this per-type record shape:{ "key": "feat", "aliases": ["feature"], "tier": "public", "emoji": "🎉", "label": "Features", "breakingPolicy": "optional" }emojiandlabelare separate fields (not a combinedheader). Consumers needing a pre-rendered string concatenate them. The 15 types in canonical render order:feat,drop,deprecate,fix,sec,perf,internal,refactor,tests,tooling,ci,deps,ai,docs,fmt.fmtcarriesexcludedFromChangelog: true.Schema
packages/agents/schemas/work-types.schema.jsonis a JSON Schema (draft 2020-12) withadditionalProperties: falseeverywhere. It enforces:version(semver),tiers(the three-element array["public", "internal", "process"]),types(array)types[].key: lowercase pattern^[a-z][a-z0-9-]*$types[].tier: must be one of the values in the top-leveltierstypes[].emoji: non-empty stringtypes[].label: non-empty stringtypes[].breakingPolicy: enum offorbidden | optional | requiredtypes[].excludedFromChangelog: optional booleanCross-element uniqueness (unique
keyvalues, globally unique aliases) is asserted in the validation test, not the schema (JSON Schema can't express it cleanly).Markdown removal
packages/agents/content/skills/_data/work-types.mdis deleted. Its prose content (precedence rule, breaking-change rule, AI-instructions carve-out) moves intocommit/SKILL.md, which is the only skill that consumes those rules. The structural data lives only inwork-types.json.Skill prose updates
commit/SKILL.md"Work types reference" section is rewritten to:breakingPolicyfield (replacing the legacy "PRIMARY only" rule)summarize-change/SKILL.mdupdates:[work-types.md](../_data/work-types.md)→[work-types.json](../_data/work-types.json)Primary → Secondary → Tertiary→public → internal → processSync mechanism
codeassembly-agents installcontinues to copy_data/whole into~/.claude/skills/_data/. The newwork-types.jsonships automatically.node-monorepo-toolsfetches it via theraw.githubusercontent.comURL pattern in itsrelease-kit work-types checkcommand.Acceptance criteria
packages/agents/content/skills/_data/work-types.jsonexists with the 15-type taxonomy andemoji/labelfield shape.packages/agents/schemas/work-types.schema.jsonexists and is well-formed JSON Schema (draft 2020-12).packages/agents/content/skills/_data/work-types.mdis deleted.commit/SKILL.mdcarries the new tier vocabulary, precedence rule, breaking-change rule, and AI-instructions carve-out.summarize-change/SKILL.mdreferenceswork-types.jsonand uses tier-order phrasing.work-types-schema.test.ts) asserts the livework-types.jsonvalidates against the schema and rejects malformed inputs (unknown keys, bad enum values, duplicate keys, duplicate aliases).codeassembly-agents installshipswork-types.jsoninto~/.claude/skills/_data/without code changes (verified by an existing install test or a new one if no existing test covers_data/JSON files).work-types.md(path or content) is updated. No remaining references to PRIMARY/SECONDARY/TERTIARY tier vocabulary in skill content.node-monorepo-tools#355's schema is updated to match the agreed shape before that repo merges (separate follow-up coordinated by the ticket author).Coordination notes
node-monorepo-toolsfetches it via theraw.githubusercontent.comURL pattern. If the schema evolves, both repos update in lockstep.types[]is canonical render order. Asserted by the schema validation test.breakingPolicyfield), not tier-level. Both repos must reflect this.