---
name: okf-write
description: Writes bounded OKF mutations when another skill must invoke it.
---

# okf-write

`okf-write` is the sole path for bounded mutations against an OKF bundle. It owns every write to bundle content — concepts, statuses, relationships, and machine verification — and native file tools (direct file writes, edits, shell redirection) never substitute for it: a change made outside this skill's wrapper is untracked and unverified.

## The wrapper request

`okf-write` constructs a request for its wrapper on `stdin`:

```json
{
  "protocol": "okf-wrapper/1",
  "skill": "okf-write",
  "operation": "revise",
  "task_kind": "fix",
  "payload": {
    "cwd": "/path/to/repo",
    "bundle": "bundle-name",
    "concept": "concept-id",
    "evidence": [{ "path": "docs/source.md", "sha256": "<64 lowercase hex characters>" }]
  }
}
```

`protocol` is always the literal `okf-wrapper/1` and `skill` is always the literal `okf-write`. `operation` names one of the five bounded operations this skill performs: `create`, `revise`, `format`, `relationship`, `machine-verify`. Every one of these is bounded, so `payload` always carries non-empty `cwd`, `bundle`, and `concept`, plus whatever keys the operation itself needs — `evidence` for a claim or verification write, `effects` for a relationship change, `set` for a field change. Each `evidence` entry is an **observation binding**, not authored provenance: `{ "path": "<path relative to the active Git worktree>", "sha256": "<64 lowercase hex characters>" }`, naming material the resolution actually read and the exact bytes it read. Standard OKF `sources` remains the only authored provenance, and the wrapper never checks that the material supports the claim — the procedure judges relevance, the runtime checks only observable facts. A malformed entry, an absolute path, a `..` segment, or a malformed digest returns `UNSUPPORTED_INPUT`; a missing, unreadable, or non-regular file returns `EVIDENCE_UNAVAILABLE`; a real path outside the active worktree returns `SYMLINK_ESCAPE`; bytes that no longer hash to the accepted digest return `EVIDENCE_CHANGED`. An **empty list is valid** for `create`, a claim-affecting `revise`, and `relationship` — a human statement or a non-file tool result is real evidence, it lives in the session-local accepted proposal, and no self-attested token for it ever crosses this seam. `machine-verify` is the one operation that requires at least one matched file binding; without one it returns `EVIDENCE_REQUIRED`. `format` and non-claim metadata changes need no semantic evidence at all. `data.evidence` lists only the bindings whose current bytes still matched, and `evidence_limits` always states that semantic support is not runtime-verified and that non-file evidence exists only in the accepted proposal. A status value is not writable in v0.1.0: `set.status` returns `UNSUPPORTED_INPUT`.

`task_kind` and `scope` are top-level fields, siblings of `payload`, not keys inside it. Every one
of `okf-write`'s five operations requires a write-eligible `task_kind`, and `scope`, when supplied,
must name `payload.concept`. See
[references/wrapper-request-fields.md](references/wrapper-request-fields.md) for the full statement
of `task_kind`, `scope`, and `invocation`.

`okf-write` sends this request to `node <skill-root>/scripts/okf-write.js`, where `<skill-root>` is the directory containing this SKILL.md — never a path resolved from the current working directory or PATH.

## Exit conditions

Every wrapper call ends in exactly one of three conditions:

1. **Valid response.** Exit code 0, one JSON line on stdout. A refusal is a valid response, not a failure — a `blocked` result carrying a `data.code` such as `WRITE_TARGET_OUTSIDE_WORKTREE`, `TARGET_CHANGED`, or `EVIDENCE_UNAVAILABLE`, or a blocking finding such as `ROOT_DECLARATION_NOT_EXACT`, is a completed answer.
2. **Invalid wrapper input.** The request never parsed: malformed JSON, a wrong `skill` value, a missing `operation`, or a missing required `payload` key. Nothing on stdout, a short diagnostic on stderr, exit code 64.
3. **Internal failure.** The request parsed and the runtime threw. One complete response (`result: "failed/incomplete"`, `data.code: "RUNTIME_FAILURE"`) still lands on stdout, a `Runtime failure: ...` diagnostic goes to stderr, exit code 70.

## Delegation

The Procedure below covers a direct call. When another skill needs this write performed on its behalf rather than running `okf-write` directly, load [references/delegation.md](references/delegation.md) for the exact `okf-writer` brief shape `okf-delegate` requires and the `okf-delegation/1` receipt it returns.

## Effects this skill owns

`okf-write` owns and performs these atomic effects in v0.1.0:

- Create a small evidence-backed concept
- Small evidence-backed claim update
- Small non-claim metadata or formatting update
- Add qualifying machine verification
- Add or remove one semantic relationship
- Regenerate a directly affected index
- Append a directly affected log entry

`okf-write` owns these effects, but they are not v0.1.0 operations. The runtime returns `UNSUPPORTED_INPUT`:

- `draft -> stable`, `stable -> deprecated`, `deprecated -> stable`
- Move or rename
- Broad inbound-link or graph rewrite
- Create merge or split outputs
- Delete a demonstrably redundant concept
- Repair a directly affected mechanical link

Each atomic effect below is owned here so that it is refused here: `okf-write` is the authority that catches the request, never the one that performs it.

- Add machine verification without complete qualifying evidence
- Write an unsupported status value
- Purge unique durable knowledge
- Introduce redirects or aliases before their semantics are defined
- Edit a sanctioned Attested Computation

## The bundle-root precondition

Decision D5 also bounds every write here: mutation requires a parsed bundle-root declaration of `okf_version: "0.2"`. `v0.1.0` never creates a bundle root — a developer authors that declaration by hand before any suite write can succeed, and no bootstrap exception exists.

## Procedure

1. **Identify the bounded operation.** Match the requested change to one of `create`, `revise`, `format`, `relationship`, or `machine-verify`. Done when the operation and its required payload keys (`cwd`, `bundle`, `concept`, plus the operation-specific key) are known; not done while the change could still map to more than one operation.
2. **Construct and send the wrapper request.** Build the JSON object shown above and pipe it to the `okf-write` wrapper. Done when the process exits and one of the three outcomes above has been observed and named; not done while the outcome is unnamed or a refusal is being treated as a crash.
3. **Reconcile every requested effect.** Walk the response and account for each requested effect as applied, refused (with its `data.code`), or not run because the process failed before reaching it. A bounded write is done only when every requested effect has one of those three dispositions — one unaccounted effect leaves the write unfinished.
4. **Report within the ceiling.** A clean result is done when reported as one line: the operation and result, nothing else; not done if the full response is shown. A refusal, an internal failure, or a `failed/incomplete` result is done only with the full response, naming the gate code and next action; not done if trimmed to one line, softened, or reported as a crash. Show the full response for any result if the caller asks.
