Yoke Function Call Reference

The Yoke function-call surface is the agent-facing mutation surface for the Yoke control plane. Agents call typed function ids through one envelope shape; the dispatcher routes to a handler, verifies the calling session's claim, writes through the canonical domain owner, and emits structured events. Shell-quoted JSON payloads are not the operator path: the python3 -m yoke_core.cli.db_router ... and python3 -m yoke_core.api.service_client ... CLI commands remain as retained operator/debug adapters that build a typed FunctionCallRequest internally and dispatch through the same registry.

This file is the per-family function reference. Render the operator-readable Atlas (one row per yoke subcommand with function id + help status, plus the tool-shaped CLI, permanent, and pending rosters and live promise-vs-live contradictions) locally with python3 -m yoke_core.tools.atlas_render_docs render. Cross-link back from db-reference.md for the entry-point CLI, the domain catalog, and the structured-field discipline.

Envelope

Every function call accepts and returns the same envelope shape, defined in yoke_contracts.api.function_call:

// Request
{
  "function": "<family>.<subfamily>.<operation>",   // registered function id
  "version": 1,                                       // optional; defaults to current
  "request_id": "<uuid>",                             // dedup key; reusing returns the original response
  "actor": {                                          // who is calling
    "session_id": "<harness_sessions.session_id>",
    "actor_id": "<harness_sessions.actor_id>"
  },
  "target": {                                         // typed target ref; shape depends on function
    "kind": "item | epic_task | section | claim | process | none",
    "public_ref": "PREFIX-N",                          // client-supplied PREFIX-N (or bare sequence)
    "item_id": 1234,                                  // resolved internal items.id (machine)
    "epic_id": 833,
    "task_num": 5,
    "section_name": "Progress Log",
    "process_key": "...",
    "conflict_group": "..."
  },
  "payload": { /* function-specific typed body */ },
  "preconditions": { /* optional invariant assertions, e.g. allow_empty + reason */ },
  "options": { /* sync_github_body, ... */ }
}

// Response
{
  "function": "...",
  "version": 1,
  "request_id": "...",
  "success": true,
  "result": { /* function-specific typed result */ },
  "warnings": [{"code": "...", "step": "..."}],
  "errors":   [{"code": "...", "message": "..."}],
  "event_ids": ["..."]
}

public_ref vs internal item_id

item_id is the internal items.id integer. public_ref is the public PREFIX-N handle. A person never reads a bare internal id — not alone, and not paired with the public handle. Machine payloads (--json, HTTP result) keep integer item_id; the dispatcher does not add a sibling ref. Human CLI output is translated at the print layer (yoke_cli.transport.public_ref_display) on a display copy: item_id / current_item_id / recent_item_id / epic_id become public_ref / current_public_ref / recent_public_ref / epic_public_ref. Lookup over HTTPS uses items.public_ref.lookup. Request targets carry target.public_ref; there is no alias for a retired target key. Handlers that already know the public handle put it on result.public_ref. DB rows, events, telemetry, and tests keep bare integer item_id.

The dispatcher always emits YokeFunctionCalled. Repeated calls with the same (function, request_id) emit DispatcherIdempotencyReplay and return the cached response verbatim. The dedup store is the function_call_ledger table (exact request_id match, written alongside the emission; rows expire after the replay TTL via the events retention prune) — events stay telemetry; the ledger owns the replay decision. Partial-state failures (the primary write succeeded but a downstream sync degraded) return HTTP 207 with success=true, warnings=[...], and a DispatcherDownstreamDegraded row in events. See the yoke source-repo doc docs/event-catalog.md for the envelope schemas.

Actor identity binding (transport-symmetric)

actor.session_id may be omitted: ambient identity resolves automatically — YOKE_SESSION_ID first, then the session variables of the harness family this process actually runs under (the nearest harness ancestor in the process tree, so a harness started inside another harness's shell never answers with the outer one's inherited variable), then that family's hook-written process-anchor registry (yoke_core.domain.session_ambient_identity). An explicit payload session always binds and is the flagged operator-debug override: when it diverges from the resolved ambient, dispatcher events carry session_override: true plus the divergent ambient_session_id in context. actor_id is never trusted from the payload — it resolves server-side from harness_sessions keyed on the bound session (a contradicting supplied value rejects with actor_id_mismatch), and over https the bearer-token actor overwrites it at the boundary.

A mutating call whose registry entry requires a session rejects with actor_session_missing when none resolves — an infrastructure-bug signal (hook registration / anchor resolution failed), not a state agents should work around. A plain terminal is the exception the message names for itself: with no harness anywhere in the process tree the refusal drops the infrastructure framing and names the supported path instead — run the command from a harness session, which is what can hold the work claim it needs. Explicitly session-optional functions never reach that refusal. They are the ones a person runs before any session exists (the onboarding wizard's Apply stages and the plain-terminal CLI recipes, enumerated in yoke_core.domain.terminal_reachable_functions and checked against the registry), and one contract attributes them all: the identity binder keeps the bearer-token actor over HTTPS and binds the universe's operating human for a local call, so a session-less write has an author without each handler resolving one. Calls whose bound session has no harness_sessions row execute where downstream gates allow but are marked provenance_unverified: true in event context on both transports — unregistered-session writes are recorded, never silently trusted.

A session's own actor follows the person who started it: a launched session binds the launching actor transitively rather than the identity of the machine it runs on. session_control. calls that act on another session (message.send, session.wake, session.terminate, keepalive.hold/release, launch.) are role-checked against the TARGET's project by yoke_core.domain.session_action_authority — project membership to message, wake, hold alive, or terminate a launched worker, project owner or org admin to terminate another actor's interactive session — and each one also writes a SessionActionPerformed event into the target session's own history carrying the acting actor. Contract: docs/archive/decisions/session-actor-follows-the-person.md.

Registry, schema, and dispatch endpoints

The FastAPI app exposes three routes mounted under /v1/functions/:

Route Purpose
POST /v1/functions/call Dispatch a FunctionCallRequest; returns the typed FunctionCallResponse.
GET /v1/functions/registry Enumerate every registered function id (per family) plus metadata (stability, target_kinds, claim_required_kind, adapter_status).
GET /v1/functions/schema/{function_id} Return the JSON Schema for one function id's request body.

The same registry is enumerable in-process via yoke_core.domain.yoke_function_registry.list_entries().

Compatibility surfaces. POST /v1/functions/call and GET /v1/health are compatibility surfaces: clients and servers may run different engine versions, and both endpoints stay answerable across that skew. The server advertises its engine version in the health payload (engine_version, distinct from the constant API-contract version) and as an X-Yoke-Engine-Version response header on API responses; the CLI's https relay compares the header against the locally installed version and prints one advisory stderr warning per process on mismatch — it never blocks. Skew is expected mid-rollout; align the older side when behavior looks off.

Claim verification matrix

Every registered function declares one of five claim_required_kind values; the dispatcher verifies before the handler runs.

Value When the dispatcher enforces
None No work-claim verification. Reads, claims.work.acquire, and project-wide operator-requested operations (board.rebuild, agents.render.run, project_structure.patch.apply). Project/org permission checks remain independently enforced.
"item" Resolves the active work-claim row for target.item_id. The calling session's session_id must match. Otherwise error.code="claim_required" (HTTP 409).
"epic" Same as "item" but resolves the parent epic id from target.kind="epic_task" (target.epic_id).
"self_only" The claim itself is the target (e.g. claims.work.release). The handler reads the claim row by target and asserts actor.session_id == row.session_id.
"operator_override" Requires the calling session to carry an operator-authored bypass marker (e.g. path-claim-override). Otherwise error.code="operator_override_required".

The five values are the closed enum; the registry rejects any other string at import time.

Function families

The function id grammar is <family>.<subfamily>.<operation> validated by yoke_contracts.api.function_call.validate_function_id. Families today:

items.* — creation, structured field, section, and progress-log writes

Replaces every hand-authored printf '%s' "$content" | python3 -m yoke_core.cli.db_router items update <id> <field> --stdin / item_field_transform / sections upsert recipe.

Function id claim_required_kind Handler Result shape
items.structured_field.replace "item" yoke_core.domain.handlers.items_structured_fieldexecute_structured_write {old_lines, new_lines, verification_status}
items.structured_field.append_addendum "item" same handler → item_field_transform.append_addendum same shape
items.structured_field.section_upsert "item" same handler → item_field_transform_sections.section_upsert same shape
items.structured_field.section_append "item" same handler → item_field_transform_sections.section_append same shape
items.section.upsert "item" yoke_core.domain.handlers.items_sectionsections_cli.upsert {section_name, content_lines}
items.section.delete "item" same handler → sections_cli.delete {section_name, deleted}
items.section.get (read) None same handler → sections_cli.get {section_name, content}
items.progress_log.append "item" yoke_core.domain.handlers.items_progress_log {old_lines, new_lines, entry_count} (read-then-upsert with ordering=200)
items.scalar.update "item" yoke_core.domain.handlers.items_scalarprepare_update {field, old, new}
items.get (read) None yoke_core.domain.handlers.reads.items_get typed item payload (optional fields[])
items.public_ref.lookup (read) None yoke_core.domain.handlers.items_public_ref {refs: {internal_id: PREFIX-N}}
items.create None yoke_core.domain.handlers.items_createbacklog_create_op.execute_create {item_id, public_ref, dry_run, log, execution_instructions, execution_instructions_considered}

Canonical create — a non-web filer attests the operator instructions:

{
  "function": "items.create",
  "target":   {"kind": "global", "project_id": "yoke"},
  "payload":  {
    "title": "Fix the footer",
    "workflow": "dash",
    "instruction": "Correct the footer and verify every link.",
    "entry_surface": "cli",
    "execution_instructions_considered": true
  }
}

execution_instructions_considered is a bare boolean attestation — no content hash, no staleness window — that this filer ran yoke workflow execution-instruction resolve --workflow W --project P before authoring. Every non-web entry surface (cli, harness_skill) must send it true; without it the create refuses with execution_instructions_not_considered and a message naming that exact retrieval command for the target. web_form renders the blocks in its own UI and promotion carries an already-filed item forward, so both stay exempt, as do dry_run previews and disposable test databases. CLI adapters (yoke dash, yoke task, yoke items create) expose --execution-instructions-considered and pass it through; they never set it for the caller, and the create receipt echoes the value it was accepted under.

Canonical write — full-field replace:

{
  "function": "items.structured_field.replace",
  "request_id": "<uuid>",
  "actor":  {"session_id": "...", "actor_id": "..."},
  "target": {"kind": "item", "item_id": 42},
  "payload": {"field": "spec", "content": "# Spec\n\n..."},
  "options": {"sync_github_body": true}
}

Canonical write — additive transform (preserves prior content, appends a ## heading-led block):

{
  "function": "items.structured_field.append_addendum",
  "target":   {"kind": "item", "item_id": 42},
  "payload":  {
    "field":   "spec",
    "heading": "Refinement Addendum (2026-05-13)",
    "source":  "refine",
    "content": "..."
  }
}

The same handler accepts items.structured_field.section_upsert (replace a ## heading-led block in place) and items.structured_field.section_append (append after the block). All variants preserve the empty/shrinkage/freeze guards on execute_structured_write and report old/new line counts plus a verification status.

Canonical write — Progress Log entry:

{
  "function": "items.progress_log.append",
  "target":   {"kind": "item", "item_id": 42},
  "payload":  {"headline": "kicked off engineer dispatch", "content": "..." }
}

The handler reads the existing Progress Log section, appends a timestamped entry, and upserts at ordering=200 (the canonical Progress Log convention — see AGENTS.md § Progress Log). CLI adapter: yoke items progress-log append PREFIX-N --headline TEXT --content TEXT (or --content-file PATH).

item_worktrees.* — explicit additional lanes, reads, and recovery

Function id claim_required_kind Handler Notes
item_worktrees.create "item" yoke_core.domain.handlers.item_worktree_create.handle_create With an empty payload, idempotently ensures the sole policy-required default lane (PREFIX-N); with lane_role + branch, registers one explicit worker or integration lane. The item must be active and claimed, the path-claim worktree gate must pass, and the branch must be valid and project-unique. Multiple workers remain allowed; a second integration lane and branch-role reuse are refused.
item_worktrees.get None (read) yoke_core.domain.handlers.item_worktrees.handle_get Returns one active lane selected by payload.lane_role; result.worktree is null when no matching lane exists.
item_worktrees.list None (read) yoke_core.domain.handlers.item_worktree_paths.handle_list Returns every active lane in result.worktrees, preserving repeated worker lanes instead of collapsing by role.
item_worktrees.path_record "item" yoke_core.domain.handlers.item_worktree_paths.handle_path_record Records an absolute machine-local path after provisioning. Requires the active item claim plus preconditions.worktree_id and preconditions.branch; a released/replaced lane or changed branch fails stale instead of updating another row.
item_worktrees.release "item" yoke_core.domain.handlers.item_worktrees.handle_release Evidence-only recovery for a post-implementation stage of the item's pinned workflow on a single-implementation-lane item. Requires the fixed evidence-only-recovery reason and a fresh clean-lane attestation matching the sole active lane. The refusal names the accepted stages.

Ensure the policy-required default lane with yoke item-worktrees create PREFIX-N; register an additional branch with yoke item-worktrees create PREFIX-N --lane-role worker --branch BRANCH (use integration for the one optional integration lane). Inspect the complete active set with yoke item-worktrees list PREFIX-N --json. Ordinary worktree preparation consumes that authoritative list over either local Postgres or HTTPS, provisions every lane locally, then records each exact path through yoke item-worktrees path-record PREFIX-N --worktree-id ID --branch BRANCH --path ABSOLUTE_PATH; the path-record adapter requires the item claim and sends lane-id/branch stale-state preconditions.

The read and recovery adapters are yoke item-worktrees get PREFIX-N --lane-role implementation --field branch and yoke item-worktrees release PREFIX-N --all-active --reason evidence-only-recovery. Release first verifies that the registered path is on the registered branch and has no modified tracked or untracked files; ignored-only residue is not dirt. Any dirt or unverifiable path fails closed.

workflows.* — immutable version and item-pin operations

Function id claim_required_kind Handler Notes
workflows.definition.get None (read) yoke_core.domain.handlers.workflows_definition Lists selected immutable definitions, version history, gate catalog, and deployment flows.
workflows.item.get None (read) yoke_core.domain.handlers.workflows_versioning Returns the item's exact pin, digest, stage, posture, interpreted lane policy, and active lanes.
workflows.current.set "operator_override" same module Selects an already-published version for subsequently created items; existing pins do not change.
workflows.item.migrate "operator_override" same module Atomically migrates one item when stage/posture, active lanes and claims, approval/QA gates, and delivery bindings remain representable; label-only changes are compatible, while retroactive unsatisfied gates are refused.
workflows.item_posture.amend "item" yoke_core.domain.handlers.workflows_item_posture Sets, replaces, or clears ONE posture key on an already-filed item. The amendable roster is the item's pinned item_posture_allowlist; each key declares its own guard, so a key with none refuses as unamendable rather than stranding records. Refuses at a terminal stage, over a verification selection whose requirement already carries a recorded run, while path claims are registered under a selection being cleared, and while an owner decision is open on a cleared approval selection. Replacing a verification selection waives its unexecuted requirement snapshots, detaches the superseded plan, and attaches the new one in the same transaction.

The operator adapters are yoke workflows item get PREFIX-N, yoke workflows current set WORKFLOW VERSION, yoke workflows item migrate PREFIX-N [--version N], and yoke workflows item-posture amend PREFIX-N --verification-plan ID_OR_SLUG --reason TEXT (--help carries the per-key decision tree).

workflow_item.epic_task. and workflow_item.epic_progress_note. — epic-task amendment

Replaces every hand-authored python3 -m yoke_core.domain.epic task-update-body <epic-id> <task-num> / task-upsert / direct epic_progress_notes choreography in /yoke amend and related skills.

Function id claim_required_kind Handler Notes
workflow_item.epic_task.body_replace "epic" yoke_core.domain.handlers.workflow_item_epic_task.body_replace Wraps epic_task_crud.task_update_body; returns {old_lines, new_lines}.
workflow_item.epic_task.split "epic" same handler → epic_amend.task_split Preserves dependencies; renumbers downstream tasks atomically; returns new_task_num.
workflow_item.epic_task.reassign "epic" same handler → epic_amend.task_reassign Updates the worktree column; returns {old_worktree, new_worktree}.
workflow_item.epic_task.add "epic" same handler → epic_amend.task_add Typed payload (title, body, dependencies, …); writes via task_upsert.
workflow_item.epic_task.remove "epic" same handler → epic_amend.task_remove Cascade-removes dependency edges.
workflow_item.epic_task.metadata_update "epic" same handler → epic_amend.task_metadata_update Accepts title, context_estimate, dependencies, and other epic-task scalar fields.
workflow_item.epic_task.review_seed "epic" yoke_core.domain.handlers.workflow_item_epic_task_review.handle_review_seed Wraps epic.review_seed; idempotent requirement seed; auto-advances implementing → reviewing-implementation.
workflow_item.epic_task.review_insert "epic" same module → epic.review_insert Payload {verdict: pass/fail (case-insensitive), body}; a pass auto-advances reviewing-implementation → reviewed-implementation.
workflow_item.epic_task.review_get None (read) same module → epic.review_get Most recent review as a pipe row (id, epic_id, task_num, verdict, body, created_at); target_not_found when none.
workflow_item.epic_task.review_list None (read) same module → epic.review_list Review history newest-first; {reviews, count} where count is review ROWS (bodies are multi-line); empty list is success.
workflow_item.epic_task.body_get None (read) yoke_core.domain.handlers.workflow_item_epic_task_state.handle_body_get Wraps epic.task_get_body; returns the body verbatim.
workflow_item.epic_task.update_status "epic" same module → epic.task_update_status Non-pipeline status write + GitHub label sync; terminal success statuses refuse with pipeline_required.
workflow_item.epic_task.simulation_upsert "epic" same module → epic.simulation_upsert Epic-level target (no task_num); payload {phase, body}; parses CLEAN / GAPS FOUND; replaces prior runs for the phase.
workflow_item.epic_task.submission_receipt_get None (read) same module → epic.submission_receipt_get Payload {after_note_count}; returns the validated PASS receipt line; receipt_invalid on failing fields.
workflow_item.epic_progress_note.append "epic" yoke_core.domain.handlers.workflow_item_epic_progress_note.append Wraps yoke_core.domain.epic.progress_note_insert.

Canonical write — epic task body replace:

{
  "function": "workflow_item.epic_task.body_replace",
  "target":   {"kind": "epic_task", "epic_id": 833, "task_num": 5},
  "payload":  {"content": "..."}
}

Canonical write — epic progress note:

{
  "function": "workflow_item.epic_progress_note.append",
  "target":   {"kind": "epic_task", "epic_id": 833, "task_num": 5},
  "payload":  {"note_num": 3, "body": "..."}
}

lifecycle.* — typed lifecycle transitions

Function id claim_required_kind Handler
lifecycle.transition "item" yoke_core.domain.handlers.items_scalar.lifecycle_transition — routes through the same engines that service_client advance/... uses.
{
  "function": "lifecycle.transition",
  "target":   {"kind": "item", "item_id": 42},
  "payload":  {"from_status": "implementing", "to_status": "reviewing-implementation", "reason": "..." }
}

claims.* — work and path claim mutation

Function id claim_required_kind Handler
claims.work.acquire None (chicken-and-egg — handler asserts no active claim) yoke_core.domain.handlers.claims_work.acquire
claims.work.release "self_only" yoke_core.domain.handlers.claims_work.release
claims.steering.acquire None (payload document narrows the seat to one strategy document and atomically pairs its lock; omit it for the whole project) yoke_core.domain.handlers.claims_steering.handle_acquire; a seat or document conflict rolls back both
claims.steering.release "self_only" same handler; releases the steering claim and its paired document lock together
claims.steering.list None (project-scoped read) same handler; project/holder/active filters
steering.report.get None (handler requires the caller's live steering claim) yoke_core.domain.handlers.steering_report.handle_get — composes one report covering every held steering claim, or a single scope when --project is set; see steering-fleet-report.md.
claims.path.register "item" yoke_core.domain.handlers.claims_path.register (routes through path_claims_resolve)
claims.path.widen "item" same handler → claims_path.widen
claims.path.release "item" same handler → claims_path.release
claims.path.amend "item" same handler → claims_path.amend
claims.path.override "operator_override" same handler → existing path-claim override gate
claims.coordination_claim.acquire None yoke_core.domain.handlers.claims_coordination_claim.acquire
claims.coordination_claim.heartbeat "self_only" same handler
claims.coordination_claim.release "self_only" same handler
claims.coordination_claim.list None (read) same handler
db_claim.amend "item" yoke_core.domain.handlers.db_claim.amend — writes the db_mutation_profile and db_compatibility_attestation columns atomically through the unified payload described in items-and-epics.md § DB Claim.
db_claim.prose_check None (read) yoke_core.domain.handlers.db_claim.handle_prose_check — prose-vs-claim detector for a stored item; https-relayable. CLI: yoke db-claim prose-check PREFIX-N. Idea intake prefers the local stdin mode yoke db-claim prose-check --stdin (no DB) via the same adapter.

ephemeral_env.* — ephemeral environment lifecycle updates

Function id claim_required_kind Handler
ephemeral_env.update None (project-role auth requires items.write on the environment row's project) yoke_core.domain.handlers.ephemeral_env — updates one ephemeral_environments field by id via the authoritative ephemeral_env.cmd_update behavior. Terminal status values preserve the existing stopped_at auto-set. CLI adapter: yoke ephemeral-env update ENV-ID FIELD VALUE. Error codes: payload_invalid, not_found, invalid_field.

qa., project_structure., orchestration, reads

Function id claim_required_kind Handler
qa.requirement.update "item" yoke_core.domain.handlers.qa.handle_qa_requirement_update
qa.run.record_verdict "item" yoke_core.domain.handlers.qa_run
qa.browser_context.get (read) None yoke_core.domain.handlers.qa_browser — one requirement-scoped read for the shared case runner: the named unwaived browser-check / browser-inspection case plus (with expected_branch) the latest ephemeral_environments.deployed_sha; scoped to whichever subject the case names — an item target or a deployment_run target, exactly one — and echoes the resolved subject so ref-shaped callers learn it. Internal CLI adapter: `yoke qa browser-context get (--item PREFIX-N --deployment-run RUN-ID) --requirement-id N`.
qa.run.add / qa.run.complete "item" yoke_core.domain.handlers.qa_browser_writes — the two-phase capture shape (add lands started/captured rows, complete finalizes in place); both verify the run belongs to the targeted requirement and emit QARunStarted/QARunCaptured/QARunCompleted by field presence. CLI adapters: yoke qa run add / yoke qa run complete.
qa.artifact.add "item" yoke_core.domain.handlers.qa_artifact_add — records one qa_artifacts row against a run from either a typed artifact_handle or mutually exclusive inline content_base64 plus filename. CLI adapter: yoke qa artifact add.
Start-bound recording authority All three recording legs accept execution_claim_id: the item claim the run pinned at qa.case_execution.begin, where the dispatcher verified it. The qa_subject check accepts that claim when the live one is gone, so an hour-long gate records the verdict it earned even after the stale-session sweep reclaimed the claim or the item was handed off mid-run. Owner: yoke_core.domain.qa_start_bound_authority; the window is AUTHORITY_WINDOW_SECONDS, sized to the longest permitted case command.
Browser method execution The tool-shaped yoke qa case run --requirement-id N fetches one immutable case through qa.case_execution.get, then uses the Browser context/run/artifact ids above when its registered runner is browser_substrate. There is no aggregate Browser execution entry.
qa.requirement.list / qa.requirement.get / qa.run.list (reads) None yoke_core.domain.handlers.qa_reads — typed qa reads over the canonical column rosters (qa_constants.REQ_COLUMNS / RUN_COLUMNS; run rows include execution_status). requirement.list filters by item target (relay shape), payload epic_id, or payload deployment_run_id. CLI adapters: yoke qa requirement list / yoke qa requirement get / yoke qa run list.
qa.gate_summary.run (read) None yoke_core.domain.handlers.qa_reads.handle_qa_gate_summary — wraps yoke_core.domain.qa_gate_summary.render_gate_summary for an item or epic_task target with payload transition ∈ (reviewed-implementation, implemented); the dispatcher-backed replacement for the checkout-shaped db_router qa gate-summary agent leg. CLI adapter: yoke qa gate-summary.
qa.requirement.add / qa.requirement.add_batch "item" yoke_core.domain.handlers.qa_requirement_create — item-attached requirement creation mirroring cmd_requirement_add/add_batch (shared validators from qa_requirement_policy_validation, pinned-workflow transition validation, per-row QARequirementCreated). Single adds require workflow_transition_id; every add_batch row requires it and targets the function-call item (one claim verifies one batch). Epic-task attachment stays on the operator-debug domain CLI and also requires a valid transition; deployment-run attachment stays operator-debug and may omit it. CLI adapters: yoke qa requirement add / add-batch.
project_structure.patch.apply None (project-role auth requires project.admin on the target project) yoke_core.domain.handlers.project_structure.handle_project_structure_patch_apply — atomically applies project configuration ops. An optional item target supplies provenance context, never write authority. CLI adapter: yoke project-structure patch apply --project P --ops-json JSON [--item ITEM].
project_structure.architecture_health.get (read) None yoke_core.domain.handlers.project_structure.handle_architecture_health_get — coverage and violations for the project's declared architecture map from the shared computer (yoke_core.domain.architecture_health); {"declared": false} when no map exists. Serves the workbench Architecture page, and the board section shows the same coverage. CLI adapter: yoke project-structure architecture-health get --project P.
project_structure.architecture_draft.get (read) None yoke_core.domain.handlers.project_structure.handle_architecture_draft_get — scan-derived draft map proposal (yoke_core.domain.architecture_map_survey) for operator review; an empty tree proposes the minimal vocabulary-only map. Apply the edited payload via project_structure.patch.apply. CLI adapter: yoke project-structure architecture-draft get --project P.
projects.site.create / projects.environment.create / projects.environment.update None yoke_core.domain.handlers.projects_infrastructure_create and projects_infrastructure_update — idempotent site/environment registration plus in-place name update. Create keys a sites row by slug and an environments row by id under a project-owned site. Re-creating an existing identity reports outcome="already_present" and touches nothing (settings updates go through the settings surfaces); a slug/id owned by a different project or site refuses with a mismatch error. Update keeps the id/site stable and writes only name (prod or stage). CLI adapters: yoke projects site create / yoke projects environment create / yoke projects environment update.
board.rebuild None yoke_core.domain.handlers.orchestration.board_rebuild — the operator-requested .yoke/BOARD.md refresh. Nothing dispatches it automatically; item, lifecycle, merge, and deploy operations never rebuild the board.
board.data.get (read) None yoke_core.domain.handlers.orchestration.handle_board_data_get — server half of the board rebuild: runs the board's full DB query plan (yoke_core.board.data.collect_board_data) for the payload's query-shaping inputs (scope, config_values from DB project-policy.settings.board, zen_vision_count, repo_root_token, optional code_days upsert into project_code_days) and returns the recorded plan. The client (yoke board rebuild composition) renders markdown locally from this payload plus client-local inputs (board art, VISION entries) and writes .yoke/BOARD.md itself, so board rebuilds work identically over https and in-process. CLI adapter: yoke board data get.
overview.activation.get (read + latch) / overview.module.dismiss / overview.module.restore None yoke_core.domain.handlers.overview_activation — the workbench Overview's activation modules. The get derives every module/submodule state from universe signals in one dispatch (payload {host_facts: {machine_connected?: bool}}) and latches newly satisfied universe modules into overview_activation_facts. The wizard's machine_universe submodule and the connect_harness module answer per registered machine (yoke_core.domain.overview_machine_activation, the one machine-identity read: session_relays plus harness_sessions.machine_id today, the machine registry row once it lands): the submodule counts and names the machines, the module carries a machines list — each with its own state, activated_at, connected, harnesses, surfaces, last_seen_at, and hook-health targets (hit, hook_health, per-target last_seen_at, and approval remediation) — latched per (machine_id, module_key) in overview_machine_activation_facts, and reads activated only when every listed machine has connected a harness. The run_onboard module carries an onboard object (yoke_core.domain.overview_onboard_progress) with the latest checklist run's live run_status, superseded_by, steps_done/steps_total, next, blocker, and the scaffold_installed / strategy_docs / environments outcomes its card is written from; that run must have no open rows to activate the module, or be closed as superseded by its project's deployments (yoke_core.domain.project_onboarding_run_supersede writes that status and the overtaking deployment onto the run row), and the facts stay live under the monotone latch. CLI adapter: yoke overview activation get. The dismiss/restore pair remains browser-proxied. A hidden module leaves Overview entirely (no count, no show-again); the way back is profile.onboarding.reset. The Profile page (yoke_core.domain.handlers.profile, reached from the actor menu, all browser-proxied, every one refusing without a bound actor) is profile.get (read) — the caller's own identity (actors name, kind, id, plus the newest actor_external_identities email and sign-in issuer when linked), org and project roles, live api_tokens rows (a machine-bound token names its machine and is ended by retiring the machine, never here), the profile.time_zone preference, and the hidden-module count — with profile.token.create (raw value returned exactly once), profile.token.revoke and profile.preference.set acting only on the caller's rows, and profile.onboarding.reset deleting every overview.module.dismissed.* preference for the caller and nothing else.
harness.machine_report.upsert None yoke_core.domain.handlers.harness_machine_report — persist client-collected harness presence and approval state for one project on one machine into harness_machine_reports (payload requires machine_id). CLI adapter: yoke harness machine-report upsert --project-id N.
packets.render / packets.check None same
packets.budget.get (read) None yoke_core.domain.handlers.orchestration_packet_budget.handle_packets_budget_get — each packet role's configured line budget, its current rendered usage, and the remaining headroom, plus the same figures for the aggregate corpus. Reports the usage the size caps enforce, so trimming a packet or raising a budget starts from a measured number; character counts are usage only, since no character limit is enforced. Named by every budget-exceeded message. Client-local like its siblings: it measures the packets this checkout renders. CLI adapter: yoke packets budget get.
agents.render.run / agents.render.check None same (routes through yoke_core.domain.agents_render)
doctor.run.run (read) None yoke_core.domain.handlers.reads_misc.handle_doctor_run — machine Doctor surface: takes {project, db_path, fix, only, quick, full, runtime}, returns structured {results[], scope, project, runtime, fail_count, warn_count, pass_count, na_count}. project defaults to the project bound to the caller's checkout. runtime names the deployment destination executing the checks (local / server / hosted); omitted, the handler derives it from the runner's own evidence. Checks outside the applicable set for that project and runtime come back with severity="N/A" and the reason in detail — they are never counted as passes and never dropped. Callers must pick exactly one scope (quick, full, or only); a JSON caller missing the scope flag receives error.code="scope_required". Unknown HC slugs in only return error.code="invalid_check". The retained human CLI is yoke doctor run --json, with byte-shape parity against this function.
events.query (read) None same
items.get (read) None same
merge_queue.landing_pull_request.record / merge_queue.landing_pending.mark / merge_queue.landing.observe / merge_queue.landing_pending.clear None Internal, session-optional item functions owned by yoke merge item: record the pull request/admission; make one cadence-limited server GitHub sweep across the project's pending landings; return this lane's durable state, queue_holding, queue_entry_state, merge_when_ready, check evidence, and refresh/change times; then clear it after terminal close-out.
session_ci_wait.record None Internal, session-required global function the CI gates call the moment a run id exists (yoke watch pytest's remote selection and the QA case command-ci runner): it records the (session, project, repo, run, head sha, kind, continue command) tuple in session_ci_run_waits so the control-plane sweep (yoke_core.domain.session_ci_wait_observer) can hand the session the verdict after the turn watching the run has ended. Re-recording one run for one session is a no-op, and supersedes_run_id drops the wait a re-dispatch abandons.
github.merge_queue.readiness (read) None yoke_core.domain.handlers.github_merge_queue_readiness — item-scoped, non-mutating landing liveness read. It composes the pull request with mergeQueue(branch).entries, returns the exact queue_entry_state, and reports null arming as consumed while an entry exists rather than as cleared. CLI adapter: yoke github merge-queue readiness PREFIX-N --json.
epic_tasks.list (read) None same
path_claims.conflicts.list (read) None same
checks.file_line.run / checks.idea_readiness.run / checks.path_claim_coverage.run / checks.schema_api_context.run / checks.agents_render.run / checks.event_registry.run / checks.migration_governance.run None yoke_core.domain.handlers.reads.*

Adapter status

The CLI surfaces (db_router items update, service_client db-claim-amend, item_field_transform, epic task-update-body, etc.) remain live adapters — they construct a FunctionCallRequest internally and dispatch through the same registry. The adapter status (live, deprecated, retired, or internal) is recorded per registry entry and surfaced in the operator-readable Atlas; render it locally with python3 -m yoke_core.tools.atlas_render_docs render. An internal function is a typed service-to-service boundary without a retained operator CLI adapter, so it is excluded from CLI-adapter parity. That adapter classification does not authorize access; the function's authorization scope and guardrails enforce who may dispatch it. Skill prose, packet prose, and agent docs reference the function id; operator/debug invocations of the CLI adapter remain valid and clearly labelled.

Authoring conventions

  • Idempotency. Always set request_id from a stable id (the calling agent's turn id, a hash of the (item, field, content), etc.). Replaying with the same (function, request_id) returns the cached response from function_call_ledger and emits DispatcherIdempotencyReplay; reusing a request_id across different function ids rejects with idempotency_key_collision. Ledger rows expire after the replay TTL (function_call_ledger.LEDGER_TTL_DAYS), after which the same request_id dispatches fresh.
  • Atomicity of mutation + side effect. Functions that mutate state plus emit downstream events (sync GitHub body, rebuild board) wrap the side effect in options. Side-effect failures degrade to warnings via DispatcherDownstreamDegraded; the primary mutation either fully committed or fully rolled back.
  • Reads return typed payloads. Function-call reads (items.get, events.query, doctor.run.run) return structured objects, not parseable terminal text. Agents that branch on read output should consume the typed fields, not regex the prior CLI's stdout.
  • Verification status. Mutation handlers run a post-write re-read and report verification_status. Treat verification_status="degraded" as the same severity as a partial-state warning.

Cross-links

  • docs/event-catalog.md (a yoke source-repo doc) — YokeFunctionCalled, DispatcherIdempotencyReplay, DispatcherDownstreamDegraded envelope schemas.
  • python3 -m yoke_core.tools.atlas_render_docs render — render the operator-readable Atlas of the agent-facing surfaces locally.
  • items-and-epics.md § DB Claim — unified amendment workflow — the db_claim.amend payload shape.
  • yoke_contracts.api.function_call — Pydantic envelope models.
  • yoke_core.domain.yoke_function_dispatch — dispatcher entry point.
  • yoke_core.domain.yoke_function_registry — registry.
  • yoke_core.domain.handlers — handler registration (idempotent).

Yoke Function Call Reference

Yoke Function Call Reference · Yoke