@farmslot/recipe-harness
v0.2.2
Published
Reusable Recipe Protocol v1 runner for Farmslot.
Maintainers
Readme
@farmslot/recipe-harness
Reusable Recipe Protocol v1 runner for Farmslot.
This package executes portable recipe graphs, validates them against an action
manifest from @farmslot/protocol, invokes registered adapters, and writes the
standard artifact package:
recipe.jsonsummary.jsontrace.jsonartifact-manifest.json
It is the base runner for backend/CLI projects and the extension point for UI, React Native, browser extension, native app, and project-domain runners.
Canonical documents
- Recipe Protocol v1 — source of truth for recipe schema and official actions.
- Recipe Runner Protocol — runner manifest, adapter, and artifact guidance.
- Recipe Harness Architecture — package boundary and runtime model.
- Recipe Composition Quality — flow design and proof quality guidance.
If this README conflicts with the public Recipe Protocol v1 reference, the protocol reference wins.
Install
yarn add @farmslot/recipe-harness @farmslot/protocol
# or
npm install @farmslot/recipe-harness @farmslot/protocolSource layout
| Path | Owns |
| --------------- | --------------------------------------------------------------------------------------------------------- |
| bin/ | Published farmslot-recipe executable shim. |
| src/index.ts | Public package export surface. |
| src/core/ | Manifest-aware recipe graph execution, flow calls, predicates, HUD node shaping, and harness-local types. |
| src/adapters/ | Standard core and UI adapter factories. |
| src/runtime/ | Runtime transports for CDP, browser extensions, and React Native bridge connections. |
| src/node/ | Node-only artifact, trace, and summary writers. |
| src/cli/ | CLI entrypoint, commands, and shared CLI validation helpers. |
| test/ | Harness package and export-boundary tests mirroring public behavior. |
Public import paths
The package exports explicit public subpaths only. Internal modules under
src/core/, src/node/, and test/ are implementation details unless
listed here.
| Import path | Use for |
| ------------------------------------------------------ | ------------------------------------------ |
| @farmslot/recipe-harness | Preferred root import for runner/adapters. |
| @farmslot/recipe-harness/runner | Runner construction helpers. |
| @farmslot/recipe-harness/types | Harness-local runtime types. |
| @farmslot/recipe-harness/adapters/core | Standard backend/headless action adapters. |
| @farmslot/recipe-harness/adapters/ui | Standard ui.* adapter shell. |
| @farmslot/recipe-harness/runtime/cdp | CDP browser transport helpers. |
| @farmslot/recipe-harness/runtime/react-native-bridge | React Native bridge transport helpers. |
| @farmslot/recipe-harness/runtime/browser-extension | Browser-extension target helpers. |
| @farmslot/recipe-harness/cli | Programmatic CLI entrypoint. |
| @farmslot/recipe-harness/cli/support | Shared CLI input validation helpers. |
| @farmslot/recipe-harness/writers | Node-only JSON artifact writers. |
What belongs here
The harness owns generic execution mechanics:
- manifest-aware runner construction;
- graph execution,
callflow composition, setup/start-state/proof/teardown ordering; - standard core adapters such as
command,wait,assert_json,watch_logs, andend; - standard UI adapter wiring through a project-provided transport;
- artifact, trace, and summary writers;
- small runtime helpers for CDP, browser-extension pages, and React Native bridge transports.
Project-specific behavior stays outside this package. For example,
example.trade.place_order, checkout.ensure_cart, or backend.seed_user
belong in the project runner that imports this package.
Minimal runner
import { createRecipeRunner, createStandardCoreAdapters } from '@farmslot/recipe-harness';
import { getRecipeActionManifestActionNames } from '@farmslot/protocol';
const runner = createRecipeRunner({
actionManifest,
adapters: createStandardCoreAdapters({
actions: getRecipeActionManifestActionNames(actionManifest),
}),
});
const result = await runner.run({
recipePath: 'recipes/smoke.recipe.json',
artifactsDir: 'artifacts/recipe-run',
projectRoot: process.cwd(),
});
if (result.status !== 'pass') process.exitCode = 1;The manifest is not documentation only. Runner construction fails when:
- a recipe uses an action missing from the manifest;
- a manifest action has no adapter;
- an adapter is registered for an undeclared action, unless it is explicitly test-only;
- a recipe references an undeclared or unimplemented precondition.
CLI usage
farmslot-recipe run recipes/smoke.recipe.json \
--artifacts-dir artifacts/recipe-run \
--action-manifest action-manifest.jsonThe CLI is useful for backend/CLI projects whose recipes only need core adapters. UI, CDP, React Native, browser-extension, and domain actions require a project runner that registers the appropriate adapters.
In this monorepo, build the package before invoking the bin directly from a
clean checkout because the published bin imports compiled dist/ output:
yarn workspace @farmslot/recipe-harness build
yarn workspace @farmslot/recipe-harness farmslot-recipe --helpCustom adapter
import { defineActionAdapter } from '@farmslot/recipe-harness';
export const echoAdapter = defineActionAdapter({
action: 'example.echo',
async execute(node, context) {
const message = String(node.message ?? '');
context.logger.info(`echo: ${message}`);
return { output: { message } };
},
});The project manifest must declare example.echo before the adapter is registered.
Keep action names namespaced and durable; avoid task-specific actions that encode
one Jira ticket or one temporary assertion.
Standard UI transport
The harness provides the official UI action shell; the project supplies the transport that knows how to press, scroll, type, navigate, capture screenshots, or update the HUD in that runtime.
import { createStandardUiAdapters } from '@farmslot/recipe-harness';
const uiAdapters = createStandardUiAdapters({
actions: ['ui.press', 'ui.set_input', 'ui.scroll', 'ui.screenshot', 'app.hud'],
transport: {
async execute(action, node, context) {
return projectUiBridge.execute(action, node, context);
},
},
});Use ui.* for user-visible proof flows. Use project-domain actions for fast
setup/teardown when the goal is state convergence rather than visual proof.
Never mutate UI state directly to manufacture proof.
HUD guidance
app.hud is first-class for UI projects. The HUD should communicate the current
human intent, not internal noise.
Default guidance:
- show one concise intent line;
- keep the default HUD to one concise current-intent line; runners may internally retain parent/child flow context for expanded reviewer/debug views;
- keep debug labels, node ids, and action names out of the default view;
- keep the display minimal enough that it does not hide the proof interaction;
- record detailed metadata in trace instead of crowding the screen.
Projects may configure the HUD layout, but should preserve these semantics so reviewers can understand what the agent is doing from screenshots or videos.
Security and portability
- Run recipes from trusted sources only;
commandexecutes local shell commands. - Keep artifact paths relative to the artifact directory.
- Do not put secrets in recipe text, HUD text, trace output, screenshots, or artifact paths.
- Prefer typed domain actions or state reads over open-ended eval/debug escape hatches.
- Treat generated artifacts as reviewer evidence: deterministic, portable, and meaningful without access to the original machine.
Maintenance rules
- Keep the harness generic. No project names, ticket-specific actions, or domain behavior in this package.
- Adapters are the boundary. The harness orchestrates; transports and domain runners perform runtime-specific work.
- Manifest truth is mandatory. Actions and preconditions must be declared before they can run.
- Parameterize before multiplying. Add one flexible adapter/flow before adding several near-duplicate files.
- Trace details, HUD intent. Put diagnostics in
trace.json; reserve HUD text for concise human-facing intent. - Fail loudly. Invalid recipes, unsafe paths, missing adapters, and broken artifacts should fail the run with useful trace/summary output.
Local quality
From the Farmslot repository root:
yarn workspace @farmslot/recipe-harness quality
yarn test:recipe-harnessBefore publishing, also run package dry-run checks once publish metadata is in place. Do not publish unless package docs, canonical docs, exports, and tests all match the same Recipe Protocol v1 contract.
License
MIT. See LICENSE.
