metafine_add
A guided design assistant for new MetaFine artifacts — either a new atomic skill primitive or a new compositional task graph. It walks you through phase classification, affordance contracts, parameter signatures, and success predicates, then produces a code stub or YAML you can drop into the repo.
What it does
metafine_add is a Claude Code skill that lives at ~/.claude/skills/metafine_add/. It accelerates two recurring authoring tasks on the MetaFine platform:
- Designing a new atomic skill — picks the right phase, the required affordances, and a callable signature; produces a
@register_skillstub ready forcore/skill.py. - Designing a new task graph — decomposes a multi-step procedure into stages with appropriate success predicates; produces a YAML stub for
configs/<slug>.yaml.
It produces artifacts; it doesn't ship them. You confirm before any file is written, and nothing is pushed to git.
Invocation
$ /metafine_add skill <one-line description> $ /metafine_add task <one-line description> $ /metafine_add <description> # mode inferred from the description $ /metafine_add # interactive — agent asks "skill or task?"
If the description is too thin to act on (e.g. just "rotate"), the agent asks up to two clarifying questions before producing a stub — no endless interrogation.
Skill mode
- Phase. Classify into
interaction/continuation/bundlefrom the description's contact semantics. - Affordances. Pick the required subset from the 11-element closed set. If the operation can't be expressed within the existing set, the agent flags it and proposes either a combination or a platform-level extension.
- Signature. Standard MetaFine convention:
fn(env, target, *, <keyword params with defaults>)returningenv.last_step_info. - Stub. Generate a complete
@register_skill(...)+ function shell with a numbered TODO body for the motion logic — never a fully-implemented body, because the planning math is task-specific. - Smoke test. Suggest
python smoke_envs.pyafter the file lands.
Task mode
- Decompose. Break the procedure into an ordered list of stages.
- Pick skills. One existing skill per stage, looked up against
SKILL_REGISTRY. - Pick targets. An
(asset_id, part)per stage. The agent can fetch the target asset'scapabilities.jsonto confirm the part offers the right affordances. - Write predicates. One success predicate per stage from the 6-atom DSL (
grasped / joint_value / lifted / pose_near / placed_in / stacked_on) composed withand / or / not. - YAML. Emit a complete YAML stub for
configs/<slug>.yaml. - Next. Suggest
python record.py --task-graph configs/<slug>.yaml --trials 5.
Built-in validation
Before declaring a stub ready, the agent walks four checks:
- Skill exists — every named skill resolves in
SKILL_REGISTRY(live grep on A100 when needed). - Affordance contract holds — each target part declares all the affordances the chosen skill requires (per the asset's
capabilities.json). - Phase ordering — no continuation skill precedes its interaction; bundle skills stand alone.
- Predicate atoms in scope — only the 6 documented atoms; the agent refuses to invent new ones.
For a task graph, you can run the live validator the agent suggests:
$ python -m utils.task_graph --validate configs/<slug>.yaml
Worked examples
Skill example
# Invocation $ /metafine_add skill rotate a screw cap by 90 degrees while holding it # Agent output (excerpt) @register_skill( phase="continuation", requires=("rotatable",), defaults={"angle_deg": 90, "velocity": 0.3}, ) def hold_and_rotate(env, target, *, angle_deg=90, velocity=0.3): """Rotate the already-grasped part about its revolute joint.""" # TODO: 1. assert engagement, 2. compute target joint value, # 3. drive with PandaArmMotionPlanningSolver at `velocity`. raise NotImplementedError
Task example
# Invocation $ /metafine_add task open the cap of jar 100221 and pour into cup # Agent output (excerpt) name: open_jar_and_pour stages: - stage_name: engage_cap skill: grasp_part target: { object: 100221, part: cap } success: grasped("cap") - stage_name: twist_open skill: pure_rotate params: { angle_deg: 120 } success: and(grasped("cap"), joint_value("cap", ">=", 2.094)) - stage_name: lift_clear skill: pure_lift params: { height_m: 0.05 } success: and(grasped("cap"), lifted("cap", height_m: 0.05))
Limits
- No remote writes. The agent proposes; you confirm; only then it writes a local file. It never modifies anything on A100.
- Closed-set discipline. 11 affordances. 6 predicate atoms. 3 phases. The agent refuses to invent variants and routes you to the platform extension path if your need is genuinely new.
- Stubs, not implementations. Skill stubs come with numbered TODO bodies — the motion-planning code is task-specific and the agent won't speculate.
- Pair with
metafine_help. When the design choice depends on platform context ("which skill already does X?", "what does pure_rotate actually return?"),metafine_addcalls into the same routing logic asmetafine_help.