v1.14.0
Changed
-
Model and effort for the 17 subagent specialists now resolve from one registry, and
three separate defects closed with it.skills/model-profiles.jsonis the only
hand-authored place that names a model or an effort level for any agent on any host;
each charter declares ametadata.model_tier(replacingmetadata.model_hint) and
scripts/lib/model-profiles.tsresolvestier + host + profile → {model, effort}at
generate time. Before this, 184 of 304 model facts were hand-copied across six surfaces,
and the four per-host tables ingenerate-subagent-artifacts.ts,
subagent-parity.test.tsandFEATURES.mdcould — and did — disagree.Three shipping defects, not one cleanup:
- Cross-host tier drift on three roles, changing five shipped pins.
navigator,
requirements-analystandplannereach carried contradictory tiers across hosts.
The sharpest proof was insideFEATURES.mditself:navigator's Claude and Codex
rationale cells held the same sentence — "no frontier reasoning needed" — beside a
standard-tier model on one host and a light-tier one on the other. Normalized to one
tier per role, sonavigatordrops to the light tier on Claude,requirements-analyst
rises to standard on OpenCode, andplannerrises to deep on OpenCode. - The Cursor emitter had never produced a valid agent file. It emitted
toolsand
reasoningEffort— neither is a Cursor frontmatter key — plus a human-readable
display name inmodel:where Cursor requires a model ID, and noreadonly, which
is Cursor's only documented permission mechanism. All 17 Cursor agents now emit only
Cursor's documented fields, withreadonly: trueon the 14 read-only charters.
model:isinheriton every tier: Cursor publishes no display-name→ID mapping and
its catalog lists no entry for two of the three models previously pinned there, so
inheritis the documented default rather than a guessed ID.cursor-agent modelsis
the discovery path, and restoring differentiation is a registry-only change. - OpenCode was sending
nameandmetadatato the model provider as bogus model
options on every subagent invocation. OpenCode's documented rule forwards
unrecognized frontmatter keys to the provider as model options, so these were not
inert — this was live behaviour, not hygiene.name:is gone (OpenCode takes the agent
name from the filename, which already yieldsmassa-ai-<n>), and the
massa-ai-owned: trueownership marker moves from frontmattermetadata:to a
<!-- massa-ai-owned: true -->body comment. It moves rather than being deleted
becausemassa-ai-config agents uninstallscopes by that literal substring: removing
it would have matched zero files, printedremoved 0, and orphaned 17 installed
agents. The substring is unchanged, so uninstall also still matches agent files an
older version installed in the frontmatter form.
Profiles are open data: adding, renaming or removing one is a registry edit with no
TypeScript type, enum, or doc table to update. Selection is--profile=<name>>
MASSA_AI_MODEL_PROFILE> registryhostDefaults[host], with no fourth rank — an
unknown name at any rank is a named error, never a silent fallback to a default model —
andvalidateRegistryreports every violation in one throw instead of one per run.
Resolution is build-time because no host resolves a per-agent model from an env var;
switching profiles means regenerating. One consequence is documented rather than worked
around:CLAUDE_CODE_SUBAGENT_MODELset to a real model silently defeats every registry
pin on Claude, because it overrides frontmatter.FEATURES.mdloses its four 17-row
per-host tables and all four rationale columns in favour of one role→tier table, guarded
by a doc-drift test;bun run verify:model-idsprobes the installed harness CLIs for
unresolvable IDs and skips an absent CLI with a named reason instead of passing vacuously.Merge note:
maingained thejudgeandmeta-judgecharters (2 more specialists,
17 total) from a concurrently-merged PR while this branch was in review. Both still
declaredmetadata.model_hintunder the retired convention; merging this branch onto
that state migrates them tometadata.model_tier: deep— matching their original
Claude/Codex pins (opus/gpt-5.6-sol, both this registry'sdeeptier) — and their
Cursor/OpenCode output now goes through the same emitter fixes as the other 15 (Cursor
inheritinstead of the raw charter hint; OpenCode dropsname/metadata).That normalization moves two more shipped model pins, which is a behaviour change and not
bookkeeping: on OpenCodejudgegoesopencode-go/deepseek-v4-pro→opencode-go/minimax-m3
andmeta-judgegoesopencode-go/kimi-k3→opencode-go/minimax-m3. Both had the same
cross-host drift this release removes —judgeshipped deep on Claude and Codex but light on
OpenCode. Note the side effect:judge-with-debatewants per-slot model diversity, and one
tier resolves to one model per host, so the two charter defaults now coincide on OpenCode.
That affects the fallback only — the workflow requests per-slot models at dispatch time
where the host supports it, and names the degraded caseDIVERSITY DEGRADEDper its own
contract. - Cross-host tier drift on three roles, changing five shipped pins.