Expand description
The typed-transform write surface (#837 piece A): POST /v1/transform,
and the shared apply_transform that lex ws transform also calls.
The typed-transform write surface (#837 piece A).
POST /v1/transform lets an agent harness make a typed edit — one of
#280’s four transforms — straight through the op log, instead of editing
text and running lex publish. The same code path backs lex ws transform
(an embedded on-disk store, no server): [apply_transform] is the single
function both call, so the two cannot diverge.
§Request
{
"branch": "main", // REQUIRED. Never the server's global current branch.
"intent": { // optional; absent => explicitly unattributed (#970)
"prompt": "why", "model": "provider/name", "session": "s-1", "issue_id": "..."
},
"transform": { "kind": "...", ... } // kind-specific, below
}kind | params | ops emitted |
|---|---|---|
replace_match_arm | from_stage_id, match_node, arm_index, new_body (CExpr) | ReplaceMatchArm |
rename_local | from_stage_id, let_node, new_name | RenameLocal |
inline_let | from_stage_id, let_node | InlineLet |
extract_function | from_stage_id, expr_node, spec {name, type_params?, params, return_type, effects?} | AddFunction + ModifyBody |
from_stage_id must be the stage the branch head currently binds to the
function’s signature (stale ids are refused with 409). This is the same
payload lex repair --apply --transform takes.
§Response (200)
{ ok, branch, kind, op_id, op_ids, prev_head, new_head, new_stage_id, extracted?, intent: { intent_id, session_id, unattributed } } —
op_id is the last op emitted (the new head); op_ids lists all of them
(two for extract_function); extracted is { sig_id, stage_id } of the
new function.
§Errors
400 malformed body / missing branch / blank intent.prompt; 404 unknown
branch or stage; 409 stale from_stage_id, no-op transform, or a function
not on the branch head; 422 the transform did not apply (unknown node,
wrong node kind, …) or the result fails the write-time gate — with the
diagnostics under detail.errors. Every refusal leaves the branch head
unchanged and writes no op and no intent.
§Intent
Attribution follows lex publish (#970): an absent intent is recorded as
an explicitly unattributed intent, never as none. A session that is not
supplied defaults, like publish’s cli-<pid>-<epoch>, to a per-process
http-<pid>-<epoch> — so an omitted session makes the OpId
non-reproducible; pin session for a deterministic OpId. The resolved
ids are echoed in the response.
Structs§
- Applied
- What a successful transform landed.
- Extract
Spec - Wire form of
lex_ast::ExtractFnSpec. - Intent
Spec - The wire form of an intent: every field optional.
Enums§
- Transform
Spec - A typed transform request; the JSON shape matches
lex repair --transform.
Constants§
- UNATTRIBUTED_
PROMPT - The prompt recorded when a write declares none (#970). Deliberately not a
plausible-looking prompt: it must be impossible to mistake a synthesized
intent for one a caller supplied, and it is a fixed string so it is exactly
matchable (
lex recall --predicatelists every unattributed op).
Functions§
- apply_
transform - Apply
spectobranchthrough the store’s gated apply path, attributing every op tointent. The one functionPOST /v1/transformandlex ws transformshare. - build_
intent - Build (not record) the Intent for a write from its optional parts. The one
implementation
lex publish,lex ws transformand the HTTP write endpoints share, so an unattributed write looks the same whichever door it came through.default_sessionis only called whensessionisNone. - default_
http_ session - The session id for an HTTP write that gave none: per-process, like
publish’s
cli-<pid>-<epoch>, and for the same reason (a constant default would collapse every anonymous write into one bogus session). - split_
model_ ref provider/name→(provider, name). A bare name is attributed to providercli;None→("cli", "unknown"). The model ref feeds the content- addressed IntentId, so the default must be stable, not empty.