Skip to main content

HarnessAdapter

Trait HarnessAdapter 

Source
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§

Source

fn label(&self) -> String

Baseline. The kebab-case identifier used in CLI flags, dispatch.json, and the staged conditions.json.

Source

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§

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.)

Source

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.

Source

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”).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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".

Implementors§