fix(agents): omit model field from all 50 bundled agents#336
Conversation
OpenCode's docs say subagents with no model field inherit the invoking primary agent's model — the desired portable behavior. The literal `model: inherit` was undocumented and produced ProviderModelNotFoundError on OpenCode older than ~v1.13.x (pre anomalyco/opencode#17888). Omitting the field works on every OpenCode version. Strip model: inherit from all 50 bundled agents. Flip the content-integrity gate: previously required `model: inherit`, now requires the field to be absent. Update the violation message to explain the why and link to the OpenCode docs and upstream PR. Update test fixtures for both directions: - writeAgent helper now writes agents without a model field - the suite that previously asserted "missing/non-inherit/empty/null" as violations now asserts "any present model value (including the literal 'inherit')" as violations - the integration test that constructed an agent fixture with no model field to trigger a violation now constructs one with `model: inherit` (which, post-flip, is a violation) Refs: https://opencode.ai/docs/agents/, anomalyco/opencode#17888
The skill spec previously mandated model: inherit for bundled agents. Update the spec to require omitting the model field instead. The why is the same as the agent change: subagents with no model field inherit from the invoking primary agent per OpenCode's docs, which is the portable behavior. model: inherit was undocumented and broken on OpenCode pre anomalyco/opencode#17888. Updates: - SKILL.md: reverse Identity Defaults section, common-mistakes table, validator rule list, and the spec summary bullet. - references/foundation-conventions.md: same reversal in the long-form Identity Defaults section, plus update the optional-fields table to show a non-inherit example for skill-level model overrides. The auto-generated docs/src/content/docs/reference/* files are gitignored and re-generated by bun run docs:generate during build. Refs: https://opencode.ai/docs/agents/, anomalyco/opencode#17888
Surface the no-model-field convention in repo-level AGENTS.md so contributors discover it at authoring time, not at CI failure. Cites the OpenCode docs (subagents inherit when model is unset) and the upstream PR that special-cased the literal "inherit" string in March 2026. The content-integrity gate already enforces this; this commit is a discoverability mirror for human contributors and AI agents reading AGENTS.md before authoring. Refs: https://opencode.ai/docs/agents/, anomalyco/opencode#17888
fro-bot
left a comment
There was a problem hiding this comment.
Verdict: PASS
This is a clean, well-scoped change that removes the model: inherit field from all 50 bundled agents, flips the content-integrity gate from requiring model: inherit to requiring its absence, and updates documentation to explain the rationale.
What the PR does correctly
- All 50 agents have
model: inheritremoved — verified viagrep -c "^model:" agents/**/*.mdreturning 0 for all. - Content-integrity gate (
scripts/content-integrity.ts:701-723) correctly flips frommodel !== 'inherit'violation toObject.hasOwn(parsed.data, 'model')violation, which catches any present model value (includinginherit, explicit provider IDs, empty strings, null). - Violation message is informative — cites the OpenCode docs URL and the upstream PR, so contributors hitting CI will understand why.
- Test fixtures are updated consistently —
writeAgenthelper now omits model, the "allows agents with model field omitted" test replaces the old "allows agents with model inherit" test, and the "flags any present model value" test covers inherit, hardcoded, empty, and null. - Skill frontmatter test correctly uses
model: anthropic/claude-haiku-4-5(skills ≠ agents; themodelfield is still valid for skills). - AGENTS.md, writing-systematic-skills/SKILL.md, and foundation-conventions.md all document the new policy with the same rationale and references.
- Non-object frontmatter case is now correctly ignored (no
modelkey to flag) rather than producing a spurious violation. - The integration test (
checkContentIntegrityagainst real repo) enforces zero violations at HEAD, and the content-integrity gate confirms0 violationson the PR branch.
Blocking issues
None.
Non-blocking concerns
-
Converter already strips
model: inherit— The PR description correctly notessrc/lib/converter.ts:310-313already strips this field during CC→OpenCode conversion. No change needed here, but worth a brief inline comment or changelog note that the converter's strip logic is now redundant for bundled agents (it's still useful for ad-hoc imports, so no action required). -
isAgentFilehelper path check — TheisAgentFilefunction checks for exactly 3 path segments (agents/<category>/<name>.md). This is correct and pre-existing, but worth noting it won't catch agents at unexpected depths. No change needed; just an observation.
Missing tests
None. The test suite comprehensively covers the new behavior (4 checkAgentModel tests, 1 integration test, 1 CLI test). All pass (66/66).
Risk assessment: LOW
- Likelihood of regression: Extremely low. The change removes an undocumented value (
model: inherit) that caused hard crashes on older OpenCode versions. Field omission is the documented default and works on all versions. - Blast radius: Limited to bundled agent dispatch behavior. Skills, config merging, tool registration, and bootstrap injection are unaffected.
- Reversibility: Single
git revertrestores the old state if a regression surfaces. - Security: No security implications — this tightens the integrity gate (now flags any
modelvalue on agents) rather than loosening it.
Run Summary
| Field | Value |
|---|---|
| Event | pull_request |
| Repository | marcusrbrown/systematic |
| Run ID | 25360486626 |
| Cache | hit |
| Session | ses_209459521ffe4VrjlpA5FywVu9 |
Sweep all 13 tracked plan documents to reflect their current state: - 2026-01-20 implementation + design plans: add YAML frontmatter, mark completed (initial v0.x shipped to npm; project evolved independently since). - 2026-02-08 docs-next-steps: add frontmatter, mark completed (reference pages + transform-content.ts shipped). - 2026-02-09 frontmatter-conversion + upstream-tracking: mark superseded by truth-reset; sync infrastructure deleted in PR #243. - 2026-02-12 reference-section-refresh: add frontmatter, mark completed (sidebar metadata + custom CSS shipped). - 2026-02-12 sidebar-badges + index-pages: add frontmatter, mark completed (LinkCard/CardGrid generation in transform-content.ts). - 2026-02-15 automated-resync-workflow: mark superseded; sync infrastructure was deleted before this plan shipped. - 2026-04-18 content-integrity-gate: flip active -> completed, add PR #301 link + post-merge note covering #306/#313/#319 follow-ups. - 2026-04-25 registry-automation: flip active -> completed, add PR #315 link + post-merge note (100-component auto-generated registry). - 2026-04-30 writing-systematic-skills: tick all 7 unit checkboxes, add Post-merge reconciliation explaining Unit 2 direction inversion by PR #336 (model field omission). - 2026-05-01 idempotent-plugin-registration: flip active -> completed, add PR #335 link + post-merge note covering Phase 0 probe outcome and Option-2 (empty-hooks) decision. Already-correct plans (refactor-credibility-reset, refactor-truth-reset) left untouched. No behavioral changes; documentation reconciliation only.
Why
OpenCode's documented contract for subagent model resolution is field-omitted:
The literal value
model: inheritis not documented by OpenCode and historically broke subagent dispatch. Pre-sst/opencode#17888(March 2026),Provider.parseModel("inherit")returned a non-null structure that defeated theagent?.model ?? sessionModelfallback, producingProviderModelNotFoundErroron every subagent invocation. The fix special-cases the literal string, but a user on OpenCode older than ~v1.13.x running Systematic v2.x today still gets a hard crash with no breadcrumb pointing at frontmatter.Field-omitted works on every OpenCode version and matches the documented contract.
What changes
agents/strip themodel: inheritline from their frontmatter.scripts/content-integrity.ts:701-723) flips its rule from "requiremodel: inherit" to "require the field absent". The new violation message cites the OpenCode docs and the upstream PR so contributors who hit it understand the why.writing-systematic-skillsspec (SKILL.md+references/foundation-conventions.md) reverses the prior guidance and explains the rationale.AGENTS.mdgains one Conventions bullet so contributors discover the policy at authoring time, not at CI failure.modelvalue (including the literalinherit)" as violations.What does NOT change
src/lib/converter.ts:310-313) was already strippingmodel: inheritfrom output. The conversion path was correct; only the bundled agents and the spec hadn't caught up.oh-my-openagentandoh-my-opencode-slimroute by agent name and don't read frontmattermodelat all. Their model overrides come from category-config, not agent files.Peer convention check
Audited 5 peer OpenCode plugins for bundled-agent
model:patterns:model: inheritField-omitted is the dominant peer convention (43/43 of agents in plugins that actually omit, vs. CEP which is the historical pattern Systematic inherited).
Verification
bun run typecheckbun run lintbun run buildbun test tests/unitmodelfield, includinginherit)Backward compatibility
Reversible by single revert if a real-world regression surfaces. The literal
inheritstring still works on post-#17888 OpenCode — this PR removes a deliberately undocumented value, it does not remove behavior.Leading indicators to watch
If OpenCode ever changes the field-absent default, the canaries are:
agent?.model ?? sessionModelfallback insst/opencodepackages/opencode/src/session/index.tsdefault_subagent_modelor equivalent global config keyRefs: https://opencode.ai/docs/agents/, anomalyco/opencode#17888