Skip to content

T-IIZO-per-target-overrides

State: planning/proposed · Impact: high · Complexity: medium

The canonical model says what every harness has in common, so a field only one harness carries has nowhere to live: Claude Code’s permissionMode, OpenCode’s permission block, Codex’s policy.allow_implicit_invocation. ap-overrides gives a note the last word for one target, in that harness’s own key names, without bending the shared model to fit a single runtime. The support warnings, the harness gap table and the edit form’s Overrides section all resolve to this key.

LocationRole today
solutions/agent-pants/crates/agent-adapt-core/src/frontmatter.rs#VaultFrontmatterTypes every modelled ap- key; an unmodelled one lands in unknown_ours and reaches no destination
solutions/agent-pants/crates/agent-adapt-core/src/namespace.rs#SPEC_KEYSThe spec’s own keys, outside our namespace — untouched by anything added under the ap stem
solutions/agent-pants/crates/agent-adapt-core/src/projection.rs#project_skillStrips the namespace and projects a note onto SkillContent; project_agent and project_command sit beside it
solutions/agent-pants/crates/agent-adapt-core/src/publish.rs#canonical_targetFolds every accepted spelling onto one name per destination; canonical_targets() is the roster
packages/rust/agent-adapt/src/render/frontmatter.rs#FrontmatterBuilderBuilds one target’s frontmatter through its dialect; raw_entry already writes an arbitrary key and JSON value
packages/rust/agent-adapt/src/runtime.rs#FrontmatterDialectomit_fields is how a target declines a canonical key
packages/rust/agent-adapt/src/render/hooks_json.rs#render_hooks_jsonSerializes hooks with no seam for a per-target key
packages/rust/agent-adapt/src/render/command_toml.rs#render_command_tomlSerializes one command with no seam for a per-target key
solutions/agent-pants/docs/vault/decisions/entity-kind-and-frontmatter-namespace.mdThe ap stem rule and the field roster a new key joins
solutions/determined/crates/determined-core/src/wire/mod.rs#AgentSkillNoteFieldsThe writable frontmatter surface: carries ap_targets, nothing per target
solutions/determined/experiences/agent-pants/app/components/ApTargetsControl.vueEdits ap-targets — which destinations, never what one of them receives
solutions/determined/experiences/agent-pants/app/utils/fieldSpec.ts#FIELD_SPECSOne entry per modelled field, each with the kinds it applies to

A note may carry ap-overrides: a map keyed by canonical target, each value a map written in that harness’s own key names — permissionMode: plan for claude, permission: {bash: ask} for opencode, policy.allow_implicit_invocation: true for codex. Canonical fields render first and the override map merges last, over the rendered output for that runtime only. Nothing an override says reaches another target.

Three rules hold at the seam. A target key the capability matrix does not know for that harness is a refusal naming both the target and the key, never a silent write. A target name outside canonical_target is the existing unknown-target refusal. An override whose value equals what the projection already emits is reported as a redundant-override diagnostic, not a refusal.

ap-overrides sits under the vault’s configured stem like every other key Agent Pants owns, so SPEC_KEYS and the spec’s six fields are unaffected, and the emit-side strip keeps the key off every destination.

A per-target body — ap-overrides.<target>.body: "note" — is decided here and lands off. The body is what the author reads and edits, and a second body per target splits the note in a way nothing else in the model does. The decision is written down so a later task can reopen it.

  1. Model the key. VaultFrontmatter gains overrides: BTreeMap<String, Map<String, Value>>, read in take_from. Each map key folds through publish::canonical_target; an unfoldable name is the existing unknown-target refusal. A value that is not a map is the same wrong-shape refusal the other typed keys already raise.
  2. Validate override keys against the capability matrix from T-HLEW-harness-capability-matrix. A key the matrix does not list for that target is refused, naming both. Decision inside this step: a target the matrix has no entry for refuses every override rather than passing them through, so an unmapped harness cannot receive unchecked keys.
  3. Merge in the frontmatter renderer. FrontmatterBuilder gains an override map applied after every canonical field, through the existing raw_entry. Decision inside this step: an override outranks FrontmatterDialect::omit_fields, because the author named that target explicitly.
  4. Give render_hooks_json and render_command_toml the same merge, so a hook and a command accept overrides on the same terms as a skill’s frontmatter.
  5. Report redundancy. The renderer compares the pre-merge and post-merge value per key and returns a diagnostic where they are equal. Diagnostics travel with the publish preview; they never block a write.
  6. Carry the key on the wire. AgentSkillNoteFields gains ap_overrides, round-tripped by write_note; FIELD_SPECS gains an entry so the field docs and the form can name it.
  7. Document it: the ap-overrides row in docs/vault-layout.md and in docs/frontmatter-reference.md, and the field roster in the namespace decision.
  8. Record the per-target-body decision as declined, with the reason, in the namespace decision.
AreaNote
solutions/agent-pants/crates/agent-adapt-core/src/frontmatter.rsVaultFrontmatter::overrides, parsed and refused in take_from
solutions/agent-pants/crates/agent-adapt-core/src/projection.rsCarry the overrides map onto the projection the renderer receives
solutions/agent-pants/crates/agent-adapt-core/src/publish.rsFold override target keys through canonical_target; surface refusals and diagnostics
packages/rust/agent-adapt/src/render/frontmatter.rsMerge the target’s override map last, via raw_entry
packages/rust/agent-adapt/src/render/hooks_json.rsSame merge for a hook’s rendered entry
packages/rust/agent-adapt/src/render/command_toml.rsSame merge for a command’s TOML
packages/rust/agent-adapt/src/runtime.rsNote that an override outranks omit_fields
solutions/determined/crates/determined-core/src/wire/mod.rsAgentSkillNoteFields::ap_overrides
solutions/determined/crates/determined-agent-skills/src/lib.rsRound-trip ap-overrides through write_note and the note detail
solutions/determined/experiences/agent-pants/app/utils/fieldSpec.tsA FIELD_SPECS entry for ap-overrides
solutions/determined/experiences/agent-pants/docs/vault-layout.mdWhere overrides sit and what they reach
solutions/determined/experiences/agent-pants/docs/frontmatter-reference.mdThe ap-overrides key reference
solutions/agent-pants/docs/vault/decisions/entity-kind-and-frontmatter-namespace.mdAdd ap-overrides to the field roster; record the declined per-target body
solutions/agent-pants/crates/agent-adapt-core/tests/Fixtures for an accepted override, an unknown key, an unknown target, a redundant override
  • AC-1: A note carrying ap-overrides.claude.permissionMode: plan publishes to claude with that key in the rendered frontmatter, and to codex, gemini-cli and opencode without it.
  • AC-2: ap-overrides appears in no rendered output for any target — the emit-side namespace strip covers it, asserted by a test over the claude and portable renders.
  • AC-3: An override key the matrix does not list for that target refuses, and the refusal text names the target and the key.
  • AC-4: An override target name outside canonical_target refuses unknown-target.
  • AC-5: An override whose value equals the projection’s own output produces a redundant-override diagnostic and still publishes.
  • AC-6: A hook’s hooks.json entry and a command’s TOML each accept an override for their target, covered by one test apiece.
  • AC-7: write_note round-trips ap-overrides byte-identically when nothing else changed.
  • AC-8: docs/frontmatter-reference.md documents ap-overrides, and the namespace decision records the per-target body as declined with its reason.

Member of milestone M-BMFD, from the user’s planning request of 2026-09-07: where a harness diverges too far for the canonical model to map onto it, a note may carry a target-specific override, and that is a feature rather than an escape hatch. The divergence is catalogued in solutions/agent-pants/docs/vault/reference/harness-comparison.md and in the assessment solutions/agent-pants/docs/vault/design/workflow-and-ux-assessment.md. The harness key names come from Claude Code subagents, OpenCode and Codex CLI, all fetched 2026-09-07.

T-HLEW-harness-capability-matrix


← Back to Tasks