pub trait HarnessAdapter {
Show 27 methods
// Required methods
fn label(&self) -> String;
fn skills_dir(&self, repo_root: &Path) -> Option<PathBuf>;
// Provided methods
fn run_capabilities(&self) -> HarnessRunCapabilities { ... }
fn config_dir_names(&self) -> Vec<String> { ... }
fn tool_vocabulary(&self) -> ToolVocabulary { ... }
fn staged_slug(
&self,
prefix: &str,
iteration: u32,
condition: &str,
skill_name: &str,
) -> String { ... }
fn validate_stage_name(&self, _name: &str) -> Result<(), String> { ... }
fn rewrites_frontmatter_name(&self) -> bool { ... }
fn advertises_staged_slug_name(&self) -> bool { ... }
fn render_available_skills_block(&self, skills: &[AvailableSkill]) -> String { ... }
fn skill_surface_phrase(&self) -> String { ... }
fn skill_unresolved_phrase(&self) -> String { ... }
fn cli_events_filename(&self) -> Option<String> { ... }
fn parse_cli_events(&self, _path: &Path) -> Result<Vec<ToolInvocation>> { ... }
fn parse_cli_events_full(&self, _path: &Path) -> Result<TranscriptSummary> { ... }
fn transcript_surfaces_skill_invocation(&self) -> bool { ... }
fn cli_model_flag(&self) -> Option<String> { ... }
fn install_guard(
&self,
_stage_root: &Path,
_guard_exe: &Path,
_ttl: Option<Duration>,
) -> Result<PathBuf> { ... }
fn guard_armed_message(&self) -> Option<String> { ... }
fn guard_verdict(
&self,
_payload: &str,
_marker: Option<GuardMarker>,
) -> Option<String> { ... }
fn guard_hook_cleanup_dir(&self, _stage_root: &Path) -> Option<PathBuf> { ... }
fn detect_shadowed_skills(
&self,
_scan_root: &Path,
_staged_skill_names: &[&str],
) -> Option<PluginShadowReport> { ... }
fn render_plan_mode_context(&self, profile_text: &str) -> String { ... }
fn has_dispatch_recipes(&self) -> bool { ... }
fn cli_next_steps(&self, _ctx: CliDispatchContext<'_>) -> String { ... }
fn cli_manifest_section(
&self,
_ctx: CliManifestContext<'_>,
) -> Option<Vec<String>> { ... }
fn cli_judge_next_steps(&self, _ctx: CliJudgeContext<'_>) -> Option<String> { ... }
}Expand description
The behavior that varies by harness. Generic dispatch code depends on this trait, never on a concrete harness variant. See the module docs for the baseline-vs-enhancement contract.
Required Methods§
Sourcefn label(&self) -> String
fn label(&self) -> String
Baseline. The kebab-case identifier used in CLI flags,
dispatch.json, and the staged conditions.json.
Sourcefn skills_dir(&self, repo_root: &Path) -> Option<PathBuf>
fn skills_dir(&self, repo_root: &Path) -> Option<PathBuf>
Baseline. The project-local directory staged skills live under for
this harness. Under --no-stage nothing is staged into it, so a
baseline harness may point this at any repo-local path its discovery
would read. None when the harness declares no skills directory —
native staging is then unavailable and the run preflight forces
--no-stage (each SKILL.md is inlined into its dispatch prompt).
Provided Methods§
Sourcefn run_capabilities(&self) -> HarnessRunCapabilities
fn run_capabilities(&self) -> HarnessRunCapabilities
The run options the generic run preflight may accept for this
harness. The default is the baseline: no write guard, --bootstrap and
--stage-name allowed alongside --no-stage. Override alongside the
enhancement that changes support (e.g. wiring the write guard flips
supports_guard).
Sourcefn config_dir_names(&self) -> Vec<String>
fn config_dir_names(&self) -> Vec<String>
The project-local config dir names this harness reads or the adapter
writes (e.g. .claude). Staging excludes every harness’s config dirs
when copying a skill’s sibling assets, so a stray checked-in config dir
never rides into a staged env. Via
all_config_dir_names this list
also feeds the guard’s Bash tamper rule and detect-stray-writes’
staging-dir lookbehind, so adding a dir here automatically grows the
write-guard’s deny surface. List the parent of
skills_dir plus any hook/config dirs the adapter
writes.
Sourcefn tool_vocabulary(&self) -> ToolVocabulary
fn tool_vocabulary(&self) -> ToolVocabulary
The tool names this harness’s guard hook payloads and parsed transcripts
use, grouped by role. Via
all_tool_vocabulary this feeds the guard
arbiter’s tool classification and detect-stray-writes’ invocation audit,
so list every name this harness’s surfaces produce — even names another
harness also uses; the union dedups. Default empty: a harness with no
guard and no transcript parser contributes nothing.
Sourcefn staged_slug(
&self,
prefix: &str,
iteration: u32,
condition: &str,
skill_name: &str,
) -> String
fn staged_slug( &self, prefix: &str, iteration: u32, condition: &str, skill_name: &str, ) -> String
Enhancement: native staging. Build the conspicuous staged-skill
slug. The default underscore form is fine for any harness without
naming rules; a harness with constrained skill names (e.g. OpenCode)
overrides it. prefix must be preserved so cleanup prefix-scans still
find the staged dir.
Sourcefn validate_stage_name(&self, _name: &str) -> Result<(), String>
fn validate_stage_name(&self, _name: &str) -> Result<(), String>
Enhancement: native staging. Validate a staged-skill identifier
(generated slug or --stage-name override) against this harness’s
naming rules. The default accepts anything.
Sourcefn rewrites_frontmatter_name(&self) -> bool
fn rewrites_frontmatter_name(&self) -> bool
Enhancement: native staging. Whether a staged skill’s frontmatter
name: is rewritten to its slug so the harness’s repo-local discovery
resolves the staged copy.
Sourcefn advertises_staged_slug_name(&self) -> bool
fn advertises_staged_slug_name(&self) -> bool
Enhancement: native staging. Whether the skill-under-test is advertised in the available-skills block under its staged slug (vs. its natural name). True for Codex, whose repo-local discovery keys on the rewritten frontmatter name. (OpenCode also rewrites the frontmatter to the slug yet still advertises the natural name — a known inconsistency tracked for a separate fix.)
Sourcefn render_available_skills_block(&self, skills: &[AvailableSkill]) -> String
fn render_available_skills_block(&self, skills: &[AvailableSkill]) -> String
Enhancement: native staging. Render the discoverable skills the way
this harness natively surfaces them (e.g. Claude Code’s Skill-tool
list, Codex’s ## Skills, OpenCode’s <available_skills> XML). The
default is a neutral bulleted list.
Sourcefn skill_surface_phrase(&self) -> String
fn skill_surface_phrase(&self) -> String
Enhancement: native staging. How a staged skill is described as discoverable in the neutral slug-disambiguation line (e.g. “via the Skill tool”).
Sourcefn skill_unresolved_phrase(&self) -> String
fn skill_unresolved_phrase(&self) -> String
Enhancement: native staging. The lead-in for the fallback “read the
skill from <path>” instruction when the staged identifier can’t be
resolved.
Sourcefn cli_events_filename(&self) -> Option<String>
fn cli_events_filename(&self) -> Option<String>
Enhancement: transcript parser. The filename (under a task’s
outputs/ dir) this harness’s one-shot CLI writes the captured
transcript to. None when no transcript ingest is wired — the ingest
pipeline then never calls the parsers below.
Sourcefn parse_cli_events(&self, _path: &Path) -> Result<Vec<ToolInvocation>>
fn parse_cli_events(&self, _path: &Path) -> Result<Vec<ToolInvocation>>
Enhancement: transcript parser. Parse the events file this harness’s one-shot CLI wrote (the captured transcript) into ordered tool invocations.
Sourcefn parse_cli_events_full(&self, _path: &Path) -> Result<TranscriptSummary>
fn parse_cli_events_full(&self, _path: &Path) -> Result<TranscriptSummary>
Enhancement: transcript parser. The full-summary counterpart of
parse_cli_events: tool invocations, deduped
token usage, duration, and final message text.
Sourcefn transcript_surfaces_skill_invocation(&self) -> bool
fn transcript_surfaces_skill_invocation(&self) -> bool
Enhancement: transcript parser. Whether the parsed transcript
exposes a deterministic skill-invocation event the __skill_invoked
meta-check can match. False for Codex (its JSONL has no skill-tool
event), which routes the meta-check to the LLM-judge fallback.
Sourcefn cli_model_flag(&self) -> Option<String>
fn cli_model_flag(&self) -> Option<String>
Enhancement: model flag. The native model-selection flag accepted
by this harness’s CLI. None means no model-selection support is
wired.
Sourcefn install_guard(
&self,
_stage_root: &Path,
_guard_exe: &Path,
_ttl: Option<Duration>,
) -> Result<PathBuf>
fn install_guard( &self, _stage_root: &Path, _guard_exe: &Path, _ttl: Option<Duration>, ) -> Result<PathBuf>
Enhancement: write guard. Arm the write guard using this harness’s
native pre-tool hook surface, returning the staged marker path. The
guard’s allowed roots are derived from stage_root (the isolated env /
agent cwd), so it bounds the agent to the same env boundary that
isolates its reads.
Sourcefn guard_armed_message(&self) -> Option<String>
fn guard_armed_message(&self) -> Option<String>
Enhancement: write guard. The banner printed after --guard
successfully arms, describing the harness’s native hook surface and how
to remove it. None for a harness with no write guard (its
install_guard errors), in which case no banner
is printed.
Sourcefn guard_verdict(
&self,
_payload: &str,
_marker: Option<GuardMarker>,
) -> Option<String>
fn guard_verdict( &self, _payload: &str, _marker: Option<GuardMarker>, ) -> Option<String>
Enhancement: write guard. Evaluate a PreToolUse hook payload
against marker, returning the serialized deny verdict to print on
stdout, or None to allow. The default fails open — a harness with no
guard never denies — matching the hook entry points’ contract that a
guard invocation can never brick a session.
Sourcefn guard_hook_cleanup_dir(&self, _stage_root: &Path) -> Option<PathBuf>
fn guard_hook_cleanup_dir(&self, _stage_root: &Path) -> Option<PathBuf>
Enhancement: write guard. A hook-config dir the guard install
created outside skills_dir (e.g. Codex’s
.codex/), which teardown prunes when restoring the original config
leaves it empty. None when the guard writes only under existing dirs.
Sourcefn detect_shadowed_skills(
&self,
_scan_root: &Path,
_staged_skill_names: &[&str],
) -> Option<PluginShadowReport>
fn detect_shadowed_skills( &self, _scan_root: &Path, _staged_skill_names: &[&str], ) -> Option<PluginShadowReport>
Enhancement: shadow preflight. Detect staged skill names that are
also discoverable from the operator’s live environment (e.g. Claude
Code’s enabled plugins or global skills dir), which contaminates the
with/without comparison. scan_root is a real staged env root — its
project-local settings participate in detection. None when the
harness has no shadow preflight (the default) or nothing is shadowed.
Sourcefn render_plan_mode_context(&self, profile_text: &str) -> String
fn render_plan_mode_context(&self, profile_text: &str) -> String
Enhancement: plan-mode context. Wrap a plan-mode profile as an
operating-context layer. The shared <system-reminder> default
usually suffices; a harness with a real native plan mode could inject
it differently.
Sourcefn has_dispatch_recipes(&self) -> bool
fn has_dispatch_recipes(&self) -> bool
Enhancement: dispatch recipes. Whether a copy-pasteable per-task
exec command is wired (the descriptor’s [dispatch] exec_template).
false means RUNBOOK.md / dispatch-manifest.md carry handoff
guidance without a per-task command recipe, and the run preflight
warns naming that limitation.
Sourcefn cli_next_steps(&self, _ctx: CliDispatchContext<'_>) -> String
fn cli_next_steps(&self, _ctx: CliDispatchContext<'_>) -> String
Enhancement: dispatch recipes. The Next: guidance printed after
run: how to dispatch each task through this harness’s one-shot CLI
and then ingest. Empty when no dispatch recipe is wired.
Sourcefn cli_manifest_section(
&self,
_ctx: CliManifestContext<'_>,
) -> Option<Vec<String>>
fn cli_manifest_section( &self, _ctx: CliManifestContext<'_>, ) -> Option<Vec<String>>
Enhancement: dispatch recipes. Extra dispatch-manifest.md lines
describing this harness’s dispatch recipe (command template, parallel
recipe, ingest note). None when the harness contributes no manifest
section.
Sourcefn cli_judge_next_steps(&self, _ctx: CliJudgeContext<'_>) -> Option<String>
fn cli_judge_next_steps(&self, _ctx: CliJudgeContext<'_>) -> Option<String>
Enhancement: dispatch recipes. The post-grade / post-ingest
judge dispatch guidance for this harness. None leaves the generic
judge handoff in place.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".