Step protocol v2
Field tables are generated from the JSON Schemas the factory validates against.
Step protocol v2
Field tables are generated from the JSON Schemas the factory validates against.
Handshake
The one stdout line a step prints when KUSAW_HANDSHAKE=1.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
continue_hint | string | no | One-line hint telling a person how to end this interactive step. | 2 |
description | string | no | One-line summary of what the step does. | 2 |
egress | array of string | no | Hosts the step says it needs (GF-132). Grants nothing; missing hosts are listed as a validate warning and are never auto-allowed. | 2 |
features | array of string | no | Optional protocol features this step implements. Known values: atlas_scan, atlas_chunk, atlas_embed, atlas_map, milestone_check, atlas_tools, model_variants. | 2 |
interactive | boolean | yes | True when the step needs a person at the terminal. | 2 |
name | string | yes | Step name as the factory should display it. | 2 |
needs_env | array of object | no | Optional list of environment variables the program expects. Grants nothing; undeclared secrets fail with secret_not_declared. | 2 |
needs_env[].name | string | yes | Environment variable name. | 2 |
needs_env[].secret | boolean | yes | True when the value is a secret. Grants nothing. | 2 |
needs_paths | object | no | Optional paths the program expects to see. Grants nothing; a listed path that is not visible in the attempt's sandbox fails with dependency_missing. | 2 |
needs_paths.read | array of string | no | Paths the program expects to read. | 2 |
needs_paths.write | array of string | no | Paths the program expects to write. | 2 |
notes | enum live, start | no | When this step can take steer notes: live (appended while running) or start (next step start). Omitted means start. | 2 |
outputs_schema | object | no | JSON Schema for result.outputs (inline object or a path relative to the step). The factory validates outputs against it. An invalid schema is E4 at handshake (GF-100). | 2 |
protocol_versions | array of integer | yes | Protocol versions this step speaks. | 2 |
type | const handshake | yes | Message type. Always handshake. | 2 |
version | string | yes | Step implementation version. | 2 |
Request
The JSON document written to a step's stdin, or to KUSAW_REQUEST for an interactive step.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
artifacts_dir | string | yes | Directory the step should write artifacts into. | 2 |
change_set_id | string | no | Stable id for this run's change set. | 2 |
completion_grace_seconds | integer | no | Seconds the factory waits after a result for this process to exit before stopping it. | 2 |
config | object | yes | Free-form settings from this step's config key. | 2 |
connectors | object | no | Per-attempt factory-connectors proxy (GF-115). Omitted when the factory has no connectors or this step may not call them. | 2 |
connectors.mcp_config | string | no | Absolute path of the attempt mcp.json that includes factory-connectors. | 2 |
connectors.socket | string | no | Absolute path of the attempt unix socket. | 2 |
connectors.tools | array of object | no | Tools listed on factory-connectors for this step. | 2 |
connectors.tools[].description | string | no | Tool description. | 2 |
connectors.tools[].input_schema | object | no | JSON Schema for arguments. | 2 |
connectors.tools[].name | string | yes | Proxy tool name connector__tool. | 2 |
context | object | yes | Task, earlier steps, and recovery fields the step can see. | 2 |
context.atlas | object | no | Atlas context for atlas_scan, atlas_chunk, atlas_embed, and atlas_map, and the agent-tools view (repos, tools) on ordinary steps. | 2 |
context.atlas.commit | string | no | Commit SHA the Atlas reflects. | 2 |
context.atlas.dims | integer | no | atlas.embedding.dims on an atlas_embed request. | 2 |
context.atlas.files | array of string | no | Relative paths inside root. | 2 |
context.atlas.model | string | no | atlas.embedding.model on an atlas_embed request. | 2 |
context.atlas.out_dir | string | no | Directory a custom atlas_map writer should write page files into. | 2 |
context.atlas.overview_cap_tokens | integer | no | Token cap for the overview page on an atlas_map request. | 2 |
context.atlas.pages_dir | string | no | Directory that already holds accepted pages the writer may read (module pages for the overview). | 2 |
context.atlas.pages_due | array of object | no | Pages a custom atlas_map writer should produce. | 2 |
context.atlas.pages_due[].kind | string | no | overview, module, apis, or conventions. | 2 |
context.atlas.pages_due[].module | string | no | Module name on a module page. | 2 |
context.atlas.pages_due[].slug | string | no | Page slug (overview, apis, conventions, or a module slug). | 2 |
context.atlas.pages_due[].sources | array of string | no | Snapshot-relative paths this page covers. | 2 |
context.atlas.provider | string | no | atlas.embedding.provider on an atlas_embed request. | 2 |
context.atlas.repo | string | no | Repo label being scanned, chunked, or embedded. | 2 |
context.atlas.repos | array of object | no | Run repos as Atlas tools see them. A missing Atlas has commit null and no overview_path. | 2 |
context.atlas.repos[].behind | boolean | no | True when the Atlas commit is behind local main. | 2 |
context.atlas.repos[].commit | string or null | no | Atlas commit SHA, or null when the repo has no Atlas. | 2 |
context.atlas.repos[].label | string | yes | Repo label. | 2 |
context.atlas.repos[].overview_path | string | no | Attempt-local copy of the overview page. | 2 |
context.atlas.root | string | no | Absolute path of the raw folder (scan) or snapshot/ (chunk and atlas_map). | 2 |
context.atlas.texts | array of object | no | Chunks to embed on an atlas_embed request, in batches of 64. | 2 |
context.atlas.texts[].id | string | yes | Chunk hash or query id. | 2 |
context.atlas.texts[].text | string | yes | Redacted text to embed. | 2 |
context.atlas.tools | object | no | How a custom step reaches read_map and search_code. | 2 |
context.atlas.tools.mcp_config | string | no | Path of the attempt MCP config that lists factory-atlas. | 2 |
context.atlas.tools.socket | string | no | Path of the attempt-local unix socket. | 2 |
context.bench | object | no | Benchmark replay this request belongs to. Omitted for ordinary runs. Custom steps and scorers receive it on replays (GF-124). | 2 |
context.bench.kind | const review | no | Present on review-step benchmark replays (GF-125). Omitted for ordinary (run) replays. | 2 |
context.bench.origin | enum fresh, private, public, unknown | yes | User-stated origin of the task: fresh, private, public, or unknown. | 2 |
context.bench.repeat_no | integer | yes | 1-based repeat index of this replay. | 2 |
context.bench.task | string | yes | Benchmark task name. | 2 |
context.bench.variant | string | yes | Variant name for this replay, including baseline. | 2 |
context.budget | object | no | The step's provider's tightest usage window (GF-127). Omitted when no budget is configured. | 2 |
context.budget.max | number | yes | Window maximum. | 2 |
context.budget.provider | string | yes | Provider name, or total for the calendar budget. | 2 |
context.budget.resume_at | string | no | RFC 3339 time when the window will have room again. Empty when under the limit. | 2 |
context.budget.used | number | yes | Usage already counted in this window. | 2 |
context.candidate | object | no | The best-of-N candidate this attempt belongs to (GF-129). Omitted on the parent pipeline and on the select step. | 2 |
context.candidate.count | integer | yes | How many candidates the stage is running. | 2 |
context.candidate.label | string | no | Attempt label when the stage used attempts. | 2 |
context.candidate.mode | enum pick, compare | no | pick chooses a winner; compare records every attempt without picking. Default is pick. | 2 |
context.candidate.model | string or null | no | Attempt model, or null when the attempt left it as configured. | 2 |
context.candidate.number | integer | yes | 1-based candidate number. | 2 |
context.candidate.provider | string or null | no | Attempt provider, or null when the attempt left it as configured. | 2 |
context.candidate.stage | string | yes | Candidates stage name. | 2 |
context.candidate.variant | object | no | Overlay applied to this candidate. Empty object when none. | 2 |
context.candidates | array of object | no | Finished candidates as the select step sees them (GF-129). Omitted outside mode select. | 2 |
context.candidates[].branch | string | yes | Working branch factory/---c or -- when labelled. | 2 |
context.candidates[].cost_usd | number or null | no | Spend attributed to this candidate, or null when none was reported. | 2 |
context.candidates[].diff | object | yes | Changed files and line counts versus the fork point. | 2 |
context.candidates[].diff.added | integer | yes | Lines added. | 2 |
context.candidates[].diff.files | integer | yes | Changed file count. | 2 |
context.candidates[].diff.removed | integer | yes | Lines removed. | 2 |
context.candidates[].elapsed_ms | integer | yes | Wall time of this candidate's attempts, in milliseconds. | 2 |
context.candidates[].grade_clean | object | no | Clean-checkout grade per repo when regrade is true. Empty when not implemented. | 2 |
context.candidates[].label | string | no | Attempt label when the stage used attempts. | 2 |
context.candidates[].model_reported | string | no | Model the provider reported, or unknown when none. | 2 |
context.candidates[].model_requested | string | no | Model setting asked for on this attempt. | 2 |
context.candidates[].number | integer | yes | 1-based candidate number. | 2 |
context.candidates[].outcome | string | yes | ok, fail, reject, or error. | 2 |
context.candidates[].provider | string | no | Provider named on this attempt. | 2 |
context.candidates[].scorecard | scorecardRow | no | This attempt's scorecard row (GF-146). | 2 |
context.candidates[].scores | array of object | no | Listed scorers' results. | 2 |
context.candidates[].scores[].name | string | yes | Scorer name. | 2 |
context.candidates[].scores[].passed | boolean | yes | True when the scorer score met its threshold. | 2 |
context.candidates[].scores[].score | number | no | Numeric score when the scorer returned one. | 2 |
context.candidates[].scores[].status | string | no | Scorer status: scored, error, skipped, or not_applicable. | 2 |
context.candidates[].variant | object | no | Overlay applied to this candidate. | 2 |
context.candidates[].verify | object | yes | Repo label to pass or fail. | 2 |
context.candidates[].warnings | array of object | no | Warnings for this attempt, such as model_mismatch. | 2 |
context.candidates[].warnings[].code | string | yes | Warning code, such as model_mismatch. | 2 |
context.candidates[].warnings[].reported | string | no | Model the provider reported when code is model_mismatch. | 2 |
context.candidates[].warnings[].requested | string | no | Model asked for when code is model_mismatch. | 2 |
context.candidates[].worktree | string | no | Candidate worktree root, still present for the select step. | 2 |
context.classify | object | no | The routing item and workflows for mode classify (GF-114). Omitted outside mode classify. | 2 |
context.classify.item | object | yes | The task or idea the classifier should assign. | 2 |
context.classify.item.body | string | yes | Item body. | 2 |
context.classify.item.labels | array of string | no | Item labels. | 2 |
context.classify.item.repos | array of string | no | Repo labels. | 2 |
context.classify.item.source | string | yes | Routing source, such as add or triage:. | 2 |
context.classify.item.title | string | yes | Item title. | 2 |
context.classify.item.type | string | no | Item type from front matter or a connector. | 2 |
context.classify.workflows | array of object | yes | Workflows the classifier may pick. | 2 |
context.classify.workflows[].description | string | yes | Workflow description. | 2 |
context.classify.workflows[].name | string | yes | Workflow name. | 2 |
context.connectors | array of object | no | Context files written from connector tools (GF-115). Omitted when the factory has no connectors. | 2 |
context.connectors[].documents | array of object | no | Documents written into this context file (GF-118). Omitted for non-docs context entries. | 2 |
context.connectors[].documents[].bytes | integer | yes | Size of the converted text in bytes, after the per-document cap. | 2 |
context.connectors[].documents[].cut | boolean | yes | True when the document was cut to the per-document cap. | 2 |
context.connectors[].documents[].id | string | yes | Document id. | 2 |
context.connectors[].documents[].title | string | yes | Document title. | 2 |
context.connectors[].documents[].url | string | yes | Document URL. | 2 |
context.connectors[].file | string | yes | Absolute path of the fenced markdown file. | 2 |
context.connectors[].is_error | boolean | no | True when required is false and the call failed. | 2 |
context.connectors[].name | string | yes | Connector name plus context key, as connector.key. | 2 |
context.connectors[].sha256 | string | yes | SHA-256 of the file bytes. | 2 |
context.events_path | string or null | no | finally only: events.jsonl for this run | 2 |
context.evidence | array of object | no | Evidence files accepted for this run so far (GF-130). | 2 |
context.evidence[].caption | string | yes | Caption, at most 200 characters. | 2 |
context.evidence[].id | string | yes | Evidence id. | 2 |
context.evidence[].media | string | yes | Sniffed media type. | 2 |
context.evidence[].step | string | yes | Step that produced the evidence. | 2 |
context.failed_repos | array of object | no | Repos that failed before this step. | 2 |
context.failed_repos[].label | string | no | Failed repo label. | 2 |
context.failed_repos[].log_path | string | no | Path of the attempt log. | 2 |
context.failed_repos[].message | string | no | Short human-readable summary. | 2 |
context.failed_repos[].reason_code | string | no | Typed reason for the failure. | 2 |
context.failed_repos[].step | string | no | Step id that failed. | 2 |
context.idea | string or null | no | intake only | 2 |
context.logs | object | no | The log-store fingerprint this run's task came from (GF-117). Omitted when the task is not from a log-store item. | 2 |
context.logs.connector | string | yes | Log-store connector name. | 2 |
context.logs.count | integer | yes | Events seen for this fingerprint. | 2 |
context.logs.fingerprint | string | yes | Error fingerprint (ext: or a factory hash). | 2 |
context.logs.first_seen | string | yes | First seen timestamp. | 2 |
context.logs.group | string | yes | Store grouping id, if the mapping has one. | 2 |
context.logs.last_seen | string | yes | Last seen timestamp. | 2 |
context.logs.url | string | yes | Store link for this fingerprint, if the mapping has one. | 2 |
context.notes | array of object | no | Undelivered steer notes for this step (GF-133). | 2 |
context.notes[].created_at | string | yes | When the note was stored. | 2 |
context.notes[].id | string | yes | Note id. | 2 |
context.notes[].text | string | yes | Note body. | 2 |
context.order | object or null | no | Work order this run belongs to. Omitted for ordinary runs. | 2 |
context.order.assertions | array of object | no | Assertions this check should judge (due at the milestone, after the check's selector). | 2 |
context.order.assertions[].id | string | yes | Assertion id. | 2 |
context.order.assertions[].tags | array of string | no | Tags from the contract. | 2 |
context.order.assertions[].text | string | yes | Assertion text from contract.yaml. | 2 |
context.order.base_refs | object | no | Per-repo base commit the combined change started from. | 2 |
context.order.claims | array of object | yes | Contract assertions this run should honour. | 2 |
context.order.claims[].id | string | yes | Assertion id. | 2 |
context.order.claims[].text | string | yes | Assertion text from contract.yaml. | 2 |
context.order.contract_path | string | yes | Path of the Work order contract.yaml. | 2 |
context.order.feature | string | no | Feature id when this run is for one feature. | 2 |
context.order.features | array of object | no | Work order features in this milestone and earlier, with delivered commits. | 2 |
context.order.features[].claims | array of string | yes | Assertion ids this feature claims. | 2 |
context.order.features[].commits | array of string | yes | Delivered commit SHAs for this feature. | 2 |
context.order.features[].id | string | yes | Feature id. | 2 |
context.order.features[].title | string | yes | Feature title. | 2 |
context.order.folder | string | no | Work order folder. Set during order.intake (GF-157). | 2 |
context.order.goal | string | no | Goal sentence the Work order started from. Set during order.intake (GF-157). | 2 |
context.order.id | string | yes | Work order id. | 2 |
context.order.milestone | string | no | Milestone id this run belongs to. | 2 |
context.order.milestone_refs | object | no | Per-repo commit at the milestone branch tip. | 2 |
context.order.notes_path | string | yes | Read-only copy of notes.md in this attempt's artifacts dir. | 2 |
context.order.phase | string | yes | Empty for feature, check, and fix runs. GF-164 sets readiness. | 2 |
context.order.previous_diff | string | no | Conflict diff for a GF-159 fix run. | 2 |
context.order.repos | array of string | no | Repo labels this Work order touches. Set during order.intake (GF-157). | 2 |
context.order.role | string | yes | feature, check, or fix. GF-164 may send readiness as phase instead. | 2 |
context.order.round | integer or null | no | Check or fix round, or null for a feature run. | 2 |
context.outcome | object or null | no | finally only: {status, reason} | 2 |
context.ports | object | no | Port block leased to this worktree set (GF-131). Omitted when the factory has no ports block. | 2 |
context.ports.base | integer | yes | First port of the leased block. | 2 |
context.ports.count | integer | yes | Number of ports in the block. | 2 |
context.ports.names | object | yes | Named ports from ports.names, keyed by name. | 2 |
context.regrade | object | no | Present when GF-120 regraded this run. Omitted otherwise. | 2 |
context.requeue_note | string or null | no | Note from the person who requeued this run. | 2 |
context.scorecard | object | no | The candidates-stage scorecard as the select step sees it (GF-146). Omitted outside mode select. | 2 |
context.scorecard.rows | array of scorecardRow | yes | One scorecard row per attempt. | 2 |
context.scorecard.stage | string | yes | Candidates stage name. | 2 |
context.scorecard.warning | string | no | Scorecard warning, such as cost incomplete. | 2 |
context.scorecard.weights | object | yes | Configured speed and cost weights. | 2 |
context.scorecard.weights.cost | number | yes | Cost weight from 0 to 1. | 2 |
context.scorecard.weights.speed | number | yes | Speed weight from 0 to 1. | 2 |
context.services | array of object | no | Declared services for this worktree (GF-131). Empty when none are running. | 2 |
context.services[].log | string | no | Path of the bounded service log. | 2 |
context.services[].name | string | yes | Service name. | 2 |
context.services[].ports | object | no | Named ports from the worktree lease. | 2 |
context.services[].ready_url | string | no | HTTP ready URL when the ready check is http. | 2 |
context.services[].repo | string | yes | Repo label. | 2 |
context.services[].state | string | yes | starting, ready, exited, stopped, or failed. | 2 |
context.source_link | string or null | no | intake only | 2 |
context.steps | object | yes | Earlier step results keyed by step id. | 2 |
context.subtask | object | no | The fan-out subtask this attempt belongs to (GF-126). Omitted on the parent pipeline. | 2 |
context.subtask.depends_on | array of string | yes | Subtask ids that must finish first. | 2 |
context.subtask.id | string | yes | Subtask id. | 2 |
context.subtask.owns | array of string | yes | Git pathspec globs this subtask owns. | 2 |
context.subtask.parent_spec | string | no | The parent task spec this subtask was split from. | 2 |
context.subtask.parent_task | string | yes | Parent task id. | 2 |
context.subtask.spec | string | yes | The subtask spec. | 2 |
context.subtask.title | string | yes | Subtask title. | 2 |
context.subtasks | array of object | no | Plan subtasks of this run, for SUMMARY.md and later stages. | 2 |
context.subtasks[].id | string | yes | Subtask id. | 2 |
context.subtasks[].owns | array of string | yes | Owned pathspecs. | 2 |
context.subtasks[].reason | string | no | Failure or skip reason. | 2 |
context.subtasks[].status | string | yes | pending, running, ok, gathered, failed, or skipped. | 2 |
context.subtasks[].title | string | yes | Subtask title. | 2 |
context.task | object or null | yes | The task this pipeline step is working on. Null during early intake. | 2 |
context.task.depends_on | array of string | no | Parent task ids this task stacks on. | 2 |
context.task.id | string | no | Task id. | 2 |
context.task.repos | array of string | no | Repo labels this task touches. | 2 |
context.task.spec | string | no | The task spec body. On a fan-out child this is the subtask spec. | 2 |
context.task.spec_path | string | no | Path of the spec file. | 2 |
context.task.title | string | no | Task title from the spec. | 2 |
context.tracker | object | no | The tracker item this run's task came from (GF-116). Omitted when the task is not from a tracker connector. | 2 |
context.tracker.connector | string | yes | Connector name. | 2 |
context.tracker.id | string | yes | Tracker item id. | 2 |
context.tracker.status | string | yes | Current tracker status value. | 2 |
context.tracker.status_meaning | string | yes | Factory meaning: todo, in_progress, in_review, done, cancelled, or other. | 2 |
context.tracker.url | string | yes | Tracker item URL, if the mapping has one. | 2 |
context.triage | object | no | Triage batch this request belongs to (GF-112). Omitted outside mode triage. | 2 |
context.triage.batch_id | string | yes | Triage batch id. | 2 |
context.triage.groups | array or null | no | Groups from an earlier triage step, or null before grouping. | 2 |
context.triage.groups[].id | string | yes | Group id (-g). | 2 |
context.triage.groups[].items | array of string | yes | Item ids in this group. | 2 |
context.triage.groups[].root_cause | string | yes | One line naming the shared cause. | 2 |
context.triage.items | array of object | yes | Items in the batch. | 2 |
context.triage.items[].id | string | yes | Item id (-). | 2 |
context.triage.items[].path | string | yes | Path of the copied item in the batch folder. | 2 |
context.triage.items[].title | string | yes | Item title. | 2 |
context.triage.repos | array of string | yes | Repo labels the batch was started with. | 2 |
context.verification_commands | object | no | Verification commands keyed by repo label. | 2 |
context.workflow | object | no | The workflow this run was routed to (GF-114). Omitted when the factory has no named workflows. | 2 |
context.workflow.confidence | number | no | Classify confidence when routed_by is classify. | 2 |
context.workflow.name | string | yes | Workflow name. | 2 |
context.workflow.routed_by | string | yes | explicit, rule, classify, default, or user. | 2 |
effects | object | no | Kinds this step may return and how they are applied (GF-92). Omitted when the step allows none. | 2 |
effects.allowed | array of object | yes | Kinds the step may return, with each kind's args schema and scope. | 2 |
effects.allowed[].kind | string | yes | Effect kind name. | 2 |
effects.allowed[].schema | object | no | JSON Schema for args. | 2 |
effects.allowed[].scope | enum outside, local | yes | outside waits for a human gate; local applies after the step. | 2 |
effects.applied_so_far | integer | yes | Effects already accepted in this run. | 2 |
effects.mode | enum apply, dry_run, off | yes | How the factory treats a valid plan. | 2 |
human_notes | array of object | no | Human notes for this run, with stable ids, for any step (GF-110). Gate reject notes, the requeue note, and the GF-101 resume note. | 2 |
human_notes[].id | string | yes | Stable id the step must answer in fix-mode review. | 2 |
human_notes[].source | string | yes | Where the note came from: gate, requeue, or resume. | 2 |
human_notes[].text | string | yes | Note body. Not fenced as untrusted data. | 2 |
limits | object | yes | Time, budget, and output caps still available for this attempt. | 2 |
limits.budget_left_usd | number or null | yes | Dollars left in the run budget, or null when unbounded. | 2 |
limits.final_text_bytes | integer | no | Cap on assistant final text kept in memory (1 MiB). | 2 |
limits.log_cap_bytes | integer | no | Per-stream cap for stdout.jsonl and stderr.log (50 MiB). | 2 |
limits.max_line_bytes | integer | no | Maximum stdout line the adapter accepts (1 MiB). | 2 |
limits.outputs_max_bytes | integer | no | Maximum serialized size of result.outputs (64 KiB). | 2 |
limits.time_left_ms | integer | yes | min(step timeout, run time left) | 2 |
loop | object or null | yes | Set when the attempt is inside a loop. Null otherwise. | 2 |
loop.iteration | integer | yes | Current iteration, starting at 1. | 2 |
loop.max_iterations | integer | yes | Maximum iterations allowed. | 2 |
loop.name | string | yes | Loop name from kusaw.yaml. | 2 |
loop.previous_feedback | object | yes | keyed by step id (or gate name, or 'requeue'). effects is the compact list of validation problems from a retry / effects_invalid attempt (GF-92). | 2 |
loop.previous_feedback.effects | array of object | no | Problems from the previous effects plan. | 2 |
loop.previous_feedback.effects[].index | integer | no | 0-based index in the previous plan. | 2 |
loop.previous_feedback.effects[].kind | string | no | Effect kind. | 2 |
loop.previous_feedback.effects[].message | string | no | Why it failed validation. | 2 |
mode | enum pipeline, intake, finally, atlas_scan, atlas_chunk, atlas_embed, atlas_map, check, score, match, triage, select, classify | yes | Why the step is running. check is a Work order milestone check or a readiness probe. atlas_map is a replaceable Atlas map writer. score is a custom scorer (GF-122). match is a custom review-benchmark matcher (GF-125). triage is a kusaw triage batch (GF-112). select is a best-of-N winner picker (GF-129). classify is a routing classify command (GF-114). | 2 |
prompt | object | no | Rendered prompt_file for this custom step attempt. | 2 |
prompt.args_used | array of string | yes | Placeholder names that had values. | 2 |
prompt.file | string | yes | Absolute path of the rendered prompt.md for this attempt. | 2 |
prompt.warnings | array of string | yes | Unused-argument warnings (E3). | 2 |
prompt_fence | object | no | Shared untrusted-data fence so a custom step can wrap outside text without the binary. | 2 |
prompt_fence.open_tag | const untrusted_data | yes | Opening tag name of the untrusted-data fence. | 2 |
prompt_fence.preamble | string | yes | The one line that tells the agent fenced content is data, never instructions. | 2 |
protocol_version | const 2 | yes | Protocol version of this request. Must be 2. | 2 |
repos | array of object | yes | Repos in running or verified. Failed and delivered repos are left out. | 2 |
repos[].base_ref | string | yes | Base commit this branch started from. | 2 |
repos[].branch | string | yes | Branch the step should work on. | 2 |
repos[].capabilities | object | no | Approved instructions, skills, and MCP servers for this repo (GF-80). Omitted when the repo has none. | 2 |
repos[].capabilities.instructions | array of object | no | Approved instruction files copied into the attempt. | 2 |
repos[].capabilities.instructions[].file | string | yes | Absolute path of the read-only copy. | 2 |
repos[].capabilities.instructions[].path | string | yes | Repo-relative path of the instructions file. | 2 |
repos[].capabilities.instructions[].sha256 | string | yes | SHA-256 of the committed file. | 2 |
repos[].capabilities.mcp | object | no | Approved MCP servers for this repo, or omitted when none are usable. | 2 |
repos[].capabilities.mcp.config | string | no | Absolute path of the generated mcp.json for this repo. | 2 |
repos[].capabilities.mcp.env | array of string | no | Env names set on the step process. Values are never written to files. | 2 |
repos[].capabilities.mcp.servers | array of string | no | Label-prefixed MCP server names in that config. | 2 |
repos[].capabilities.notes | object or null | no | Factory-side notes copy, or null when notes is unset. | 2 |
repos[].capabilities.notes.file | string | no | Absolute path of the read-only notes copy. | 2 |
repos[].capabilities.notes.sha256 | string | no | SHA-256 of the notes file. | 2 |
repos[].capabilities.skills | array of object | no | Approved skills copied into the attempt, named -. | 2 |
repos[].capabilities.skills[].dir | string | yes | Absolute path of the read-only skill copy. | 2 |
repos[].capabilities.skills[].id | string | yes | Label-prefixed name given to the provider. | 2 |
repos[].capabilities.skills[].name | string | yes | Skill name as declared in the repo. | 2 |
repos[].capabilities.skills[].sha256 | string | yes | SHA-256 of the skill contents. | 2 |
repos[].command_env | object or null | no | How this repo's factory commands run, or null when command_env is unset. | 2 |
repos[].command_env.shell | string | no | sh, bash, or an absolute path to a POSIX shell. | 2 |
repos[].command_env.shell_init | array of string | no | Lines run in the same shell as the command, in order. | 2 |
repos[].command_env.wrap | array of string | no | Argv prefix every command runs under. | 2 |
repos[].copied | array of object | no | Folders copied from the source checkout into this worktree before setup (GF-106). Omitted when none were copied. | 2 |
repos[].copied[].method | enum clone, reflink, copy | yes | How the factory copied this path: APFS clone, Linux reflink, or a plain copy. | 2 |
repos[].copied[].path | string | yes | Repo-relative path that was copied. | 2 |
repos[].git_control | object | no | Git control-file protection for this repo (GF-89). | 2 |
repos[].git_control.baseline_keys | array of string | yes | Repo-local program key names trusted for this run (names only). | 2 |
repos[].git_control.protected | const true | yes | The factory snapshots and restores git control files around the attempt. | 2 |
repos[].glossary_path | string or null | no | Absolute path of the glossary file in the worktree, or null when the repo has none. | 2 |
repos[].label | string | yes | Repo label from kusaw.yaml. | 2 |
repos[].salvage_ref | string | no | refs/factory/salvage// when worktree_state is reused_saved. Omitted otherwise. | 2 |
repos[].setup | array of object | no | Setup commands that ran for this repo, in order, with host then sandbox (GF-105). Omitted when none ran. | 2 |
repos[].setup[].group | enum host, sandbox | yes | Where the command was configured to run. | 2 |
repos[].setup[].index | integer | yes | 1-based index matching setup-.log across both groups. | 2 |
repos[].setup[].inside_sandbox | boolean | yes | True when the command ran inside the OS sandbox. | 2 |
repos[].setup[].log_path | string | yes | Absolute path of this command's setup log. | 2 |
repos[].setup[].status | enum ok, failed, timeout | yes | Whether the command succeeded. | 2 |
repos[].signing | object | no | Resolved signing requirement for this repo (GF-87). Omitted when signing is not required. | 2 |
repos[].signing.required | boolean | no | True when this repo's deliveries are signed. | 2 |
repos[].stacked_on | object or null | no | Parent delivery this repo started from. Omitted when the repo starts at the base branch. | 2 |
repos[].stacked_on.branch | string | no | Parent branch the commit was on. | 2 |
repos[].stacked_on.commit | string | yes | Parent delivered commit. | 2 |
repos[].stacked_on.label | string | no | Parent repo label. | 2 |
repos[].stacked_on.run_id | string | yes | Parent run that delivered this commit. | 2 |
repos[].stacked_on.task_id | string | yes | Parent task id. | 2 |
repos[].standards | string | yes | Path of the standards file for this repo, or empty. | 2 |
repos[].status | enum running, verified | yes | Whether this repo is still in progress or already verified. | 2 |
repos[].worktree | string | yes | Absolute worktree path for this repo. | 2 |
repos[].worktree_state | enum new, reused_clean, reused_saved, recreated | no | How this worktree was prepared for the attempt (GF-97). new on first start; reused_clean when HEAD matched the checkpoint with no changes; reused_saved when uncommitted changes were written to salvage_ref before reset; recreated when the folder was missing and rebuilt from the branch. | 2 |
resume | object | no | Present when the factory resumes a previous provider session for this attempt (GF-101). The step may ignore it and start fresh; report what it did in result.session.resumed_from. | 2 |
resume.fork | boolean | yes | True when the provider should fork so the old session is unchanged. | 2 |
resume.note | string | no | Optional operator note prepended to the continue prompt. | 2 |
resume.provider | string | yes | Provider of the session to continue. | 2 |
resume.session_id | string | yes | Provider session id to resume. | 2 |
run_id | string or null | yes | null during intake and triage | 2 |
sandbox | object | no | OS sandbox for this attempt (GF-88). Informational; omitted when the attempt is not sandboxed. | 2 |
sandbox.backend | enum seatbelt, bwrap, null | yes | seatbelt, bwrap, or null when off. | 2 |
sandbox.egress | object | no | Present when network is allowlist. Informational; the factory enforces the allowlist. | 2 |
sandbox.egress.allow | array of string | yes | Host names this attempt may reach. | 2 |
sandbox.egress.injected | array of string | yes | inject entry names served through the proxy. Values are omitted. | 2 |
sandbox.egress.proxy | string | yes | HTTP proxy URL the sandboxed process should use. | 2 |
sandbox.mode | enum required, off | yes | Effective sandbox mode for this attempt. | 2 |
sandbox.network | enum open, allowlist | yes | Network policy. open is the GF-88 default; allowlist routes outbound traffic through the factory egress proxy. | 2 |
sandbox.tmp | string | no | Private temp folder for this attempt. | 2 |
sandbox.writable | array of string | no | Host paths the process may write. | 2 |
step | object | yes | The step attempt being started. | 2 |
step.attempt | integer | yes | Attempt number, starting at 1. | 2 |
step.id | string | yes | Step instance id for this run. | 2 |
step.name | string | yes | step definition key in kusaw.yaml | 2 |
step.stage | string or null | no | enclosing loop or parallel name | 2 |
structured_output | object | no | Advice for how this step should produce structured output (GF-100). mode is two_step (produce then extract) or single_fallback (one call with an contract). The factory does not force custom programs to extract. | 2 |
structured_output.max_output_retries | integer | yes | Extra extract calls after the first extract try. 0 means one extract try. | 2 |
structured_output.mode | enum two_step, single_fallback | yes | How the step should collect JSON: produce-then-extract, or one call. | 2 |
task_id | string or null | yes | null during intake until write-spec sets it | 2 |
worktree | string or null | yes | absolute path of the worktree set root; null during intake | 2 |
artifact
A file a step published.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
artifact.caption | string | no | Caption when kind is evidence, at most 200 characters. | 2 |
artifact.kind | string | yes | Artifact kind, such as log or diff. | 2 |
artifact.media | string | no | Sniffed or declared media type when kind is evidence (GF-130). | 2 |
artifact.page | string | no | URL or path the evidence shows. | 2 |
artifact.path | string | yes | Path relative to KUSAW_ARTIFACTS_DIR. | 2 |
artifact.repo | string | no | Repo label the evidence belongs to. | 2 |
artifact.title | string | no | Optional display title. | 2 |
feedbackItem
One finding from a step or gate.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
feedbackItem.assertion | string | no | Assertion id this finding belongs to, on a milestone check. | 2 |
feedbackItem.file | string | no | Path the finding refers to. | 2 |
feedbackItem.line | integer | no | Line number in that file. | 2 |
feedbackItem.message | string | yes | What the finding is. | 2 |
feedbackItem.repo | string or null | no | Repo label the finding applies to. Missing or empty means every active repo. | 2 |
feedbackItem.rule | string | no | Rule id when the finding comes from a linter or reviewer. | 2 |
feedbackItem.severity | enum blocker, major, minor, info | yes | How serious the finding is. | 2 |
feedbackItem.source | string | no | Which step or gate produced the finding. | 2 |
scorecardRow
One attempt on the candidates-stage scorecard (GF-146).
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
scorecardRow.chosen | boolean | no | True when this attempt was selected. | 2 |
scorecardRow.chosen_by | string | no | builtin, or the custom select step id. | 2 |
scorecardRow.cost_known | boolean | yes | False when GF-59 reported no cost. | 2 |
scorecardRow.cost_score | number | yes | Lowest cost divided by this attempt's cost. | 2 |
scorecardRow.cost_usd | number or null | no | Normalized cost in USD, or null when unknown. | 2 |
scorecardRow.elapsed_ms | integer | yes | Wall time excluding budget suspend, in milliseconds. | 2 |
scorecardRow.gate | boolean | yes | True when the accuracy gate passed. | 2 |
scorecardRow.gate_reasons | array of string | no | Failing gate reasons, such as verify or scorer:. | 2 |
scorecardRow.label | string | yes | Attempt label, or c when unlabelled. | 2 |
scorecardRow.number | integer | yes | 1-based candidate number. | 2 |
scorecardRow.rank | integer | yes | 1-based rank among gate passers, or 0 when the gate failed. | 2 |
scorecardRow.speed_score | number | yes | Fastest time divided by this attempt's time. | 2 |
scorecardRow.total | number | yes | Weighted total among gate passers. | 2 |
stepSummary
One earlier step's result, as seen by a later step.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
stepSummary.artifacts | array of artifact | no | Files that step published. | 2 |
stepSummary.iteration | integer or null | no | Loop iteration when that step ran, or null. | 2 |
stepSummary.message | string | no | Short human-readable summary. | 2 |
stepSummary.outputs | object | no | Structured outputs from that step. | 2 |
stepSummary.reason_code | string | no | Typed reason for the outcome. | 2 |
stepSummary.status | enum ok, fail, retry, reject, skipped, killed | yes | Outcome of that step. | 2 |
Event types
One stdout line from a running step. Exactly one event shape matches.
agent_action
A short summary of what the agent did.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
agent_action.summary | string | yes | What the agent did. | 2 |
agent_action.type | const agent_action | yes | Event type. Always agent_action. | 2 |
artifact
An artifact the step published.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
artifact.caption | string | no | Caption when kind is evidence, at most 200 characters. | 2 |
artifact.kind | string | yes | Artifact kind, such as log or diff. | 2 |
artifact.media | string | no | Sniffed or declared media type when kind is evidence (GF-130). | 2 |
artifact.page | string | no | URL or path the evidence shows. | 2 |
artifact.path | string | yes | Path relative to KUSAW_ARTIFACTS_DIR. | 2 |
artifact.repo | string | no | Repo label the evidence belongs to. | 2 |
artifact.title | string | no | Optional display title. | 2 |
artifact.type | const artifact | yes | Event type. Always artifact. | 2 |
note_ack
A custom step acknowledged a steer note.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
note_ack.id | string | yes | The note id. | 2 |
note_ack.type | const note_ack | yes | Event type. Always note_ack. | 2 |
progress
Progress update.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
progress.message | string | yes | What the step is doing now. | 2 |
progress.percent | number | no | Optional completion from 0 to 100. | 2 |
progress.turn | boolean | no | True when this marks a model turn. | 2 |
progress.type | const progress | yes | Event type. Always progress. | 2 |
tool_call
A tool call the step made.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
tool_call.allowed | boolean | yes | Whether the factory allowed the call. | 2 |
tool_call.args_summary | string | no | Short summary of the arguments. | 2 |
tool_call.tool | string | yes | Tool name. | 2 |
tool_call.type | const tool_call | yes | Event type. Always tool_call. | 2 |
usage
Cumulative usage for this attempt.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
usage.context_limit | integer or null | no | Model context window only when the provider reported it. Null otherwise. | 2 |
usage.context_tokens | integer or null | no | Input size of the last model call, including cache reads and writes. Null when unknown. | 2 |
usage.cost_source | enum reported, computed, null | no | Whether the cost was reported by the model or computed from prices. | 2 |
usage.cost_usd | number or null | no | Dollar cost so far. | 2 |
usage.model | string or null | no | Model id when known. | 2 |
usage.provider | string or null | no | Provider name when this usage is billed to a named provider. | 2 |
usage.tokens_cached | integer or null | no | Cached input tokens so far. | 2 |
usage.tokens_input | integer or null | no | Input tokens used so far. | 2 |
usage.tokens_output | integer or null | no | Output tokens used so far. | 2 |
usage.type | const usage | yes | Event type. Always usage. | 2 |
Result
The step's final stdout line, or the interactive result file.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
artifacts | array of artifact | no | Files the step published under KUSAW_ARTIFACTS_DIR. | 2 |
cause | enum unclear_spec, missing_context, weak_test, wrong_permission, model_error, other | no | Coarse cause when the step failed or rejected. | 2 |
cost | object or null | no | Optional token and dollar cost for this attempt. | 2 |
cost.source | enum reported, computed, null | no | Whether the cost was reported by the model or computed from prices. | 2 |
cost.tokens_cached | integer or null | no | Cached input tokens. | 2 |
cost.tokens_input | integer or null | no | Input tokens used. | 2 |
cost.tokens_output | integer or null | no | Output tokens used. | 2 |
cost.usd | number or null | no | Reported or computed dollar cost. | 2 |
effects | array of object | no | Optional plan of typed effects the factory validates and applies (GF-92). At most 100 items; the factory enforces the cap after decode. | 2 |
effects[].args | object | no | Arguments matching the kind's schema. | 2 |
effects[].kind | string | yes | Effect kind. | 2 |
feedback | array of feedbackItem | no | Findings for later steps or a human gate. | 2 |
message | string | yes | Short human-readable summary. | 2 |
outputs | object | no | Structured outputs for later steps. At most 64 KiB serialized. order_note is a string the factory appends to the Work order notes when the attempt ends ok. | 2 |
outputs.assertions | array of object | no | Per-assertion answers from a milestone check. status is pass, fail, or unknown. | 2 |
outputs.assertions[].evidence | array of string | no | Evidence file names the step declared. | 2 |
outputs.assertions[].files | array of string | no | Repo-relative paths this answer refers to. | 2 |
outputs.assertions[].id | string | yes | Assertion id. | 2 |
outputs.assertions[].message | string | no | Reason, pointing at files when the check failed or was unknown. | 2 |
outputs.assertions[].status | enum pass, fail, unknown | yes | How this check judged the assertion. | 2 |
outputs.chunks | array of object | no | Line ranges from an atlas_chunk command. The factory reads text from snapshot/. | 2 |
outputs.chunks[].end_line | integer | no | 1-based end line. | 2 |
outputs.chunks[].kind | string | no | function, method, class, type, window, or map. | 2 |
outputs.chunks[].path | string | no | Path relative to snapshot/. | 2 |
outputs.chunks[].start_line | integer | no | 1-based start line. | 2 |
outputs.chunks[].symbol | string | no | Symbol name, empty for windows. | 2 |
outputs.errors | array of object | no | Atlas per-file scan errors. | 2 |
outputs.errors[].path | string | no | Path that failed to scan. | 2 |
outputs.errors[].reason | string | no | Why the file was skipped. | 2 |
outputs.findings | array of object | no | Atlas scan findings. Only rule_id and location fields are kept. | 2 |
outputs.findings[].end_column | integer | no | 1-based end byte column. | 2 |
outputs.findings[].end_line | integer | no | 1-based end line. | 2 |
outputs.findings[].path | string | no | Path relative to the scanned root. | 2 |
outputs.findings[].rule_id | string | no | Scanner rule id. Never a secret value. | 2 |
outputs.findings[].start_column | integer | no | 1-based start byte column. | 2 |
outputs.findings[].start_line | integer | no | 1-based start line. | 2 |
outputs.order_note | string | no | Note the factory appends to the Work order notes when the attempt ends ok. | 2 |
outputs.pages | array of object | no | Pages from an atlas_map command. file is relative to context.atlas.out_dir. | 2 |
outputs.pages[].file | string | no | Path relative to out_dir of the written Markdown file. | 2 |
outputs.pages[].slug | string | no | Page slug matching pages_due. | 2 |
outputs.scanner | object | no | Atlas scanner identity. Missing version yields a warning. | 2 |
outputs.scanner.name | string | no | Scanner name. | 2 |
outputs.scanner.version | string | no | Scanner version. | 2 |
outputs.vectors | array of object | no | Embeddings from an atlas_embed command. | 2 |
outputs.vectors[].id | string | no | Chunk hash or query id from the request. | 2 |
outputs.vectors[].vector | array of number | no | Embedding of length atlas.embedding.dims. | 2 |
phase | string | no | Optional sub-phase the step was in when it failed (GF-95). Up to 40 characters matching ^[a-z][a-z0-9_]*$. A value that does not match is ignored with a warning, not a protocol_error. | 2 |
protocol_version | const 2 | yes | Protocol version of this result. Must be 2. | 2 |
provenance | object | no | Optional custom-step provenance (GF-128). The factory type-checks strings and at most 32 tools; a wrong type is ignored, not a failure. | 2 |
provenance.model | object | no | Model the command called. Must be a string; other types are ignored. | 2 |
provenance.prompt_sha256 | object | no | SHA-256 hex of the prompt bytes the command sent. | 2 |
provenance.provider | object | no | Provider name the command called, if it reports one. | 2 |
provenance.tools | object | no | Map of tool name to version string. At most 32 entries. | 2 |
reason_code | string | yes | Typed reason for the outcome. | 2 |
recovery | array of object | no | Optional copy-paste recovery commands from a custom step (GF-98). The factory keeps at most 5 valid items (title up to 80 characters, command up to 500); extras are dropped with a warning, not a protocol_error. | 2 |
recovery[].command | string | no | Command to copy and run. | 2 |
recovery[].title | string | no | Short label for the command. | 2 |
resets_at | string | no | Optional RFC 3339 time when a usage_limit window resets (GF-127). | 2 |
retry_after_ms | integer | no | Optional wait in milliseconds the factory uses instead of the default backoff when status is retry. Values below 1,000 are ignored and the normal backoff is used. The allowed range is 1,000 to 900,000. | 2 |
session | object | no | Optional provider session the step wants the factory to record (GF-101). | 2 |
session.dir | string | yes | Working directory of the session. | 2 |
session.id | string | yes | Provider session id. | 2 |
session.provider | string | yes | Provider that owns this session. | 2 |
session.resumed_from | string | no | Session id this attempt continued. Empty or omitted when the step ignored resume and started fresh. | 2 |
status | enum ok, fail, retry, reject | yes | Step outcome. | 2 |
type | const result | yes | Message type. Always result. | 2 |
Score outputs
outputs object a custom scorer must return. score is 0 to 1, or null when the criterion does not apply.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
items | array of object | no | Locations the judge cited. The score is not recomputed from items. | 2 |
items[].file | string | no | Path the finding refers to. | 2 |
items[].line | integer | no | Line number in that file. | 2 |
items[].message | string | no | What the finding is. | 2 |
items[].repo | string | no | Repo label. | 2 |
rationale | string | no | Short reason for the score. | 2 |
score | number or null | yes | Judge score from 0 to 1, or null when not applicable. | 2 |
Environment variables
Variables the step adapter sets. A new variable appears here when it is added to the adapter list.
| Name | When | Description |
|---|---|---|
KUSAW_PROTOCOL | handshake and attempt | Step protocol version the adapter speaks. |
KUSAW_HANDSHAKE | handshake and attempt | Set to 1 during handshake so the step prints one handshake line and exits. |
KUSAW_RUN_ID | handshake and attempt | Run id for this attempt. Empty during handshake and intake. |
KUSAW_TASK_ID | handshake and attempt | Task id for this attempt. Empty during handshake and intake until write-spec sets it. |
KUSAW_STEP_ID | handshake and attempt | Step id for this attempt. Empty during handshake. |
KUSAW_WORKTREE | handshake and attempt | Worktree path for this attempt. Empty during handshake and intake. |
KUSAW_ARTIFACTS_DIR | handshake and attempt | Directory the step should write artifacts into. Empty during handshake. |
KUSAW_ATTEMPT | handshake and attempt | Attempt number, starting at 1. Empty during handshake. |
KUSAW_ITERATION | handshake and attempt | Loop iteration when the attempt is inside a loop. Empty during handshake. |
KUSAW_CONFIG_SNAPSHOT | handshake and attempt | Path of the run's read-only config snapshot. Empty during handshake. |
KUSAW_REPOS | every attempt | Comma-separated active repo labels. |
KUSAW_REPO | optional | Active repo label for a per-repo invocation. |
KUSAW_BIN | optional | Absolute path of the kusaw binary. |
KUSAW_REPO_COMMAND_ENV | optional | JSON object {shell, shell_init, wrap} or null for the attempt's repo. Set when there is one active repo or the step is per_repo. |
KUSAW_REPO_CAPABILITIES | optional | Absolute path of a JSON file with one repo's capabilities object. Set when there is one active repo or the step is per_repo. |
KUSAW_CLAUDE_COMMAND | optional | Claude Code executable for built-in steps that call it. |
KUSAW_CLAUDE_EXTRA_ARGS | optional | JSON array of extra Claude Code arguments. |
KUSAW_AGENT_PROVIDER | optional | Resolved provider for this step: claude-code or cursor. |
KUSAW_CURSOR_COMMAND | optional | Cursor CLI executable for built-in steps that call it. |
KUSAW_CURSOR_EXTRA_ARGS | optional | JSON array of extra Cursor CLI arguments. |
KUSAW_REQUEST | interactive | Path of request.json for an interactive step. The step reads this instead of stdin. |
KUSAW_RESULT | interactive | Path of result.json for an interactive step. The step writes its result here instead of stdout. |
KUSAW_EVENTS | interactive | Path of events.jsonl for an interactive step. The step appends event lines here. |
KUSAW_BASE_REF_<LABEL> | optional | Parent commit this repo is stacked on, or empty when the repo starts at the base branch. |
KUSAW_ORDER_ID | optional | Work order id when this run has an order_runs row. |
KUSAW_ORDER_NOTES | optional | Read-only copy of the Work order notes.md for this attempt. |
KUSAW_ATLAS_SOCKET | optional | Path of the attempt-local Atlas unix socket. |
KUSAW_ATLAS_TOKEN | optional | Per-attempt token for Atlas tools. |
KUSAW_ATLAS_OVERVIEW | optional | Path of the overview file when the run has one repo. |
KUSAW_TRIAGE_ID | optional | Triage batch id when this attempt belongs to kusaw triage. Empty during handshake and ordinary runs. |
KUSAW_SUBTASK | optional | Subtask id when this attempt is inside a fan-out. Empty during handshake and the parent pipeline. |
KUSAW_CANDIDATE | optional | Candidate id (c) when this attempt is inside a candidates stage. Empty during handshake and the parent pipeline. |
KUSAW_ATTEMPT_LABEL | optional | Attempt label when this step is inside a candidates stage. Empty during handshake, the parent pipeline, and when the attempt has no label. |
KUSAW_ATTEMPT_PROVIDER | optional | Attempt provider when this step is inside a candidates stage. Empty when the attempt left provider as configured. |
KUSAW_ATTEMPT_MODEL | optional | Attempt model when this step is inside a candidates stage. Empty when the attempt left model as configured. |
KUSAW_WORKFLOW | optional | Workflow this run was routed to. Empty during handshake, intake, and when the factory has no named workflows. |
KUSAW_CONNECTOR_SOCKET | optional | Path of the attempt-local factory-connectors unix socket. |
KUSAW_CONNECTOR_TOKEN | optional | Per-attempt token for factory-connectors. |
KUSAW_TRACKER_ITEM | optional | Tracker item as : when this run's task came from a tracker connector. |
KUSAW_LOG_FINGERPRINT | optional | Log fingerprint when this run's task came from a log-store connector. |
KUSAW_PROMPT_FILE | optional | Absolute path of the rendered prompt.md when this custom step has prompt_file. |
KUSAW_NOTES_FILE | optional | JSONL file of steer notes for this attempt (one {id, text, created_at} per line). |
KUSAW_STEER_LIVE | optional | Set to 1 when this Claude Code attempt keeps stdin open for live notes. |
KUSAW_SANDBOX | optional | seatbelt, bwrap, or empty. Always set; reserved names win. |
Built-in step outputs
Classify workflow (GF-114)
The routing classify answer: one workflow name, a confidence from 0 to 1, and a rationale.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
confidence | number | yes | The classifier's own estimate, not a calibrated probability. | 2 |
rationale | string | yes | Why this workflow was chosen. | 2 |
workflow | string | yes | Name of one configured workflow. | 2 |
Improvement draft output (GF-100)
JSON improvement drafting extracts for one proposal.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
change | object | yes | The proposed value or file body. | 2 |
rationale | string | yes | Why this change should be applied. | 2 |
target | string | yes | The config key or file the proposal edits. | 2 |
target_kind | enum config_key, instructions_file, skill_file | yes | What the proposal changes: a config key, an instructions file, or a skill file. | 2 |
title | string | yes | Short title for the proposal. | 2 |
Plan (GF-126)
Owned, dependency-ordered subtasks returned by a planner step. plan may be null when the work should not be split.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
plan | object | no | The split plan, or null when fan-out should run the sub-pipeline once in the parent worktree. | 2 |
reason | string | no | Why plan is null, or a short note about the split. | 2 |
Retro output (GF-100)
JSON array of improvement proposals the retro step extracts.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
[].evidence | array of string | yes | Run ids or notes that support the proposal. | 2 |
[].kind | enum deterministic_check, coding_standard, factory_config, spec_template | yes | Which kind of factory change this proposal is. | 2 |
[].rationale | string | yes | Why this change should be applied. | 2 |
[].suggested_change | string | yes | The change to make. | 2 |
[].title | string | yes | Short title for the proposal. | 2 |
Review findings (GF-125)
Findings a review step reports. Built-in review writes the same fields to artifacts/review-.json. Custom review steps return them as outputs.findings.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
findings | array of object | yes | Claimed issues and comments from the reviewer. | 2 |
findings[].file | string or null | no | Repo-relative path, or null when there is no location. | 2 |
findings[].line | integer or null | no | 1-based line, or null when there is no location. | 2 |
findings[].message | string | yes | What is wrong. | 2 |
findings[].rule | string | yes | Rule id. | 2 |
findings[].severity | enum blocker, major, minor, info | yes | How serious the issue is. info is a comment, not a claimed bug, unless --count-info. | 2 |
Review fix-mode output (GF-110)
JSON the review step extracts after it edits the worktree. findings are issues it did not fix. Every human_notes id must appear once in notes.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
changes | array of object | yes | Files this step changed, with a short summary of each change. | 2 |
changes[].file | string | yes | Repo-relative path. | 2 |
changes[].summary | string | yes | What changed in this file. | 2 |
findings | array of object | yes | Issues the reviewer did not fix. | 2 |
findings[].file | string or null | no | Repo-relative path, or null when there is no location. | 2 |
findings[].line | integer or null | no | 1-based line, or null when there is no location. | 2 |
findings[].message | string | yes | What is still wrong. | 2 |
findings[].rule | string | yes | Rule id. | 2 |
findings[].severity | enum blocker, major, minor, info | yes | How serious the remaining issue is. | 2 |
notes | array of object | yes | One answer per human note. | 2 |
notes[].action | enum addressed, declined, deferred | yes | How the reviewer handled the note. | 2 |
notes[].id | string | yes | id from request.human_notes. | 2 |
notes[].reply | string | yes | Reply stored as a run.note effect. | 2 |
Review match pairs (GF-125)
Pairs a custom matcher returns for one review-benchmark try. mode is match. bug is a planted-bug id. finding is the 0-based index into the findings array from the request.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
pairs | array of object | yes | One-to-one matches of planted bugs to findings. | 2 |
pairs[].bug | string | yes | Planted-bug id from the request. | 2 |
pairs[].finding | integer | yes | 0-based index of the matched finding. | 2 |
Review output (GF-100)
JSON the review step extracts after it reads the diff.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
findings | array of object | yes | Findings the reviewer reported. Each item is one issue. | 2 |
Candidate selection (GF-129)
The winner picked by a select step after a candidates stage. choice is a candidate number, or null when none qualify.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
choice | integer or null | no | 1-based candidate number to gather, or null to fail the stage. | 2 |
rationale | string | no | Why this candidate was chosen, or why none were. | 2 |
Triage assessments (GF-112)
Per-item assessments returned by triage-assess. Role cannot be needs-triage.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
assessments | array of object | yes | One assessment per item in the group. | 2 |
assessments[].claims | array of object | no | Claims from the item and whether they hold. | 2 |
assessments[].claims[].claim | string | yes | The claim taken from the item. | 2 |
assessments[].claims[].evidence | string | no | Why the assessment judged the claim that way. | 2 |
assessments[].claims[].holds | enum true, false, unclear | yes | Whether the claim holds. | 2 |
assessments[].difficulty | enum small, medium, large | yes | How large the change is. | 2 |
assessments[].id | string | yes | Item id. | 2 |
assessments[].questions | array of string | no | Questions to ask when role is needs-info. | 2 |
assessments[].relevant_files | array of string | no | Repo-relative paths that matter for the item. | 2 |
assessments[].role | string | yes | needs-info, ready-for-agent, ready-for-human, or wontfix. | 2 |
assessments[].verdict | string | yes | Short verdict, at most 500 characters. | 2 |
Triage groups (GF-112)
Root-cause groups returned by triage-group. Every item id appears in exactly one group. A group of one is fine.
| Name | Type | Required | Description | Since |
|---|---|---|---|---|
groups | array of object | yes | Groups of items that share a root cause. | 2 |
groups[].items | array of string | yes | Item ids in this group. | 2 |
groups[].root_cause | string | yes | One line naming the shared cause. | 2 |