Expand description
§weavatrix-refactor-plan
The protocol-independent, filesystem-independent contract for exact Weavatrix refactor plans.
The dependency direction is deliberate:
weavatrix-edit <- weavatrix-refactor-plan <- weavatrix-worktreeweavatrix-edit owns exact source edits. This crate owns the multi-operation
plan, evidence, validation, and fingerprint. weavatrix-worktree executes an
already validated plan transactionally. MCP, LSP clients, planners, sessions,
locks, confirmation tokens, journals, and rollback do not belong here.
§Contract
RefactorPlan uses schema weavatrix.refactor-plan.v1 and supports:
Modify(FileEdit): exact text edits guarded by the whole-file SHA-256;Create(CreateFile): exact UTF-8 contents at a path that must be absent;Delete(DeleteFile): deletion guarded by the whole-file SHA-256;Rename(RenameFile): an exact source hash, absent destination, and optional exact edits against the originalfromsource, applied before it is moved.
TextEdit coordinates are frozen as 1-based lines and 0-based UTF-16 code
units. This is part of v1 and is not negotiated from an LSP client.
The operations array is one simultaneous transition set, not a sequential
script. Rename chains and cycles snapshot each original input; an executor’s
deterministic commit order must not expose intermediate array states. Array
order is still retained and fingerprinted for stable evidence and
operationIndex references.
Operations use Serde’s adjacent kind / value wire shape. The value is not
an arbitrary payload: it is the typed contract for that operation.
{
"schemaVersion": "weavatrix.refactor-plan.v1",
"operation": "move_and_generate",
"operations": [
{
"kind": "rename",
"value": {
"from": "src/old.rs",
"to": "src/new.rs",
"expectedSourceSha256": "0000000000000000000000000000000000000000000000000000000000000000"
}
},
{
"kind": "create",
"value": { "path": "src/generated.rs", "contents": "// generated\n" }
}
]
}§Quick start
use weavatrix_refactor_plan::{
CreateFile, RefactorOperation, RefactorPlan, RefactorPlanLimits,
validate_executor_plan,
};
let plan = RefactorPlan::new(
"generate",
vec![RefactorOperation::Create(CreateFile::new(
"src/generated.rs",
"pub const GENERATED: bool = true;\n",
))],
);
let checked = validate_executor_plan(&plan, RefactorPlanLimits::default())?;
println!("{}", checked.fingerprint());The minimal constructor is intentionally executable. Semantic completeness is
not a filesystem safety prerequisite: a reviewed PARTIAL plan can still
contain exact, safely applicable operations.
§Evidence and completeness
Evidence is typed in Rust and flattened at the top-level JSON object. Unknown extension fields are preserved, bounded, validated for reserved-key collisions, and included in the fingerprint.
CompletenessProof is machine-comparable rather than a free-form label:
EvidenceScopehas an openkind, a stablevalue, optional portable roots, and languages;PlannerIdentityidentifies planner name/version and backend, with an optional backend version;graphRevisionpreserves missing, explicitnull, and string states.
UncertainReference must identify a safe repository path (the legacy file
spelling is accepted) or a typed subject, and must include a kind or reason.
NotModified must identify a path, typed subject, or valid operationIndex,
and must include a reason. Portable aliases and duplicate evidence entries are
rejected.
There are three entry points:
validate_consumer_plan: exact operations plus internal consistency of any recognized evidence;validate_executor_plan: the same exact-operation safety contract, exposed as an executor-specific validated wrapper;validate_planner_plan: a strict producer profile requiring completeness, RFC 3339createdAt, explicitgraphRevision, typed proof, explicit evidence arrays, and a follow-up.
Strict PARTIAL output needs at least one uncertainty or omission. Any explicit
COMPLETE claim needs a typed proof and cannot contain either.
§Safety and resource contract
Validation is pure; it does not open the repository. Before a plan can be fingerprinted or handed to an executor it checks:
- schema, operation and operation-count bounds;
- repository-relative paths,
.gitand.weavatrixexclusion, Windows device names, case/Windows suffix aliases, and Unicode NFC aliases; - exact lowercase SHA-256 preconditions;
- duplicate input/output roles, unsafe cross-operation overlaps, rename aliases, and per-file overlapping text ranges;
- edit counts/text, create bytes, distinct paths, evidence text/counts, and one combined byte/node/depth budget for every extension map;
- reserved flattened keys at plan, operation, edit, proof, scope, planner, uncertainty, omission, and subject levels.
Use parse_refactor_plan for untrusted JSON. It caps input before allocation,
limits recursion/value count, rejects duplicate object names recursively before
typed deserialization, and then runs normal validation. Generic JSON-to-map
parsing is not an equivalent security boundary because duplicate names have
already been collapsed.
§Fingerprint contract
FINGERPRINT_ALGORITHM is
weavatrix.refactor-plan.jcs-sha256.v1. The digest is:
SHA-256(UTF-8(algorithm) || 0x00 || RFC-8785-JCS(plan without top-level createdAt))The implementation uses a crate-owned streaming RFC 8785 serializer (ECMAScript
number formatting via ryu-js), orders keys by UTF-16 code units, and streams
sorted top-level fields into SHA-256. The operations array is not
materialized as one canonical byte vector. It rejects negative zero and exact
integers outside [-9007199254740991, 9007199254740991] before JCS because
those inputs are not stable I-JSON values.
Only the top-level createdAt is excluded: it records when the same plan was
produced, not what it proves or executes. A nested field named createdAt is
ordinary extension evidence and remains fingerprinted. Every operation,
precondition, completeness claim, proof, warning, and unknown extension remains
inside the digest.
canonical_plan_bytes exists for diagnostics and golden tests. Production code
should retain the PlanFingerprint returned by a validated wrapper.
§Legacy text plans
The frozen weavatrix.edit-plan.v1 types remain re-exported. Explicit,
lossless text-only helpers avoid confusing the two schemas:
RefactorPlan::from_text_edit_plan(EditPlan)maps each file toModifyand preserves completeness and every top-level extension;try_into_text_edit_plansucceeds only when every operation isModify.
The lower-level crate is also available as weavatrix_refactor_plan::weavatrix_edit.
§Conformance evidence
docs/schema/weavatrix.refactor-plan.profile.v1.schema.jsondescribes the strict producer profile and all four operation values.tests/fixtures/refactor-plan-v1.jsonlcontains Node-generated canonical JCS payloads and fingerprints checked by Rust.tests/fixtures/generate-refactor-plan-v1.mjsis the independent Node oracle.tests/fixtures/refactor-plan-conformance.jsonlbinds raw JSON cases to the runtime consumer/planner results.tests/fixtures/js-v0.1.5-ownership.jsonaccounts for all 175 legacy JavaScript tests without claiming that this crate owns planner, LSP, session, MCP, or transaction behavior.
§Measured performance
Recorded on a frozen tree against the direct predecessor, npm
weavatrix-refactor@0.1.5, with canonicalize@3.0.0 as the fingerprint oracle.
Correctness gates run before any timing: canonical JCS bytes and the
domain-separated digest must match the Node oracle exactly. Medians come from 30
samples per cell inside warmed persistent workers; the conservative column is
the JavaScript p25 divided by the Rust p75.
| Class | 500-file plan, JS -> Rust median | Conservative ratio | Scope |
|---|---|---|---|
| Cached fingerprint lookup | 0.005 -> 0.000 µs | 11.19x | Equal semantics |
| End-to-end validate + fingerprint | 3570 -> 1092 µs | 2.44x | Rust validates strictly more |
| Legacy envelope validation | 370 -> 233 µs | 1.27x | Equal declared subset |
| Parse + legacy validation | 855 -> 1018 µs | 0.65x | Equal declared subset |
These numbers were recorded against weavatrix-edit 0.1.5. That dependency has
since replaced its derived envelope codecs with hand-written ones, which sits
inside the timed region of the two decode-bearing classes, so the table stands
until a publication rerun replaces it.
Parse plus validation is the one class where this crate is slower, and only at
the largest size. The cause is not the JSON decoder: measured fairly, under a
production profile, blazingly-json decodes faster than serde_json on every
realistic corpus
(evidence).
The cost is that this class materializes an extension map per file and per edit
for members the workload never reads — skipping them decodes the same 500-file
plan roughly twice as fast — on top of path-alias canonicalization,
reserved-key scans, and size budgets that JSON.parse plus the npm validator
do not perform at all. So the row measures strictly more work.
Skipping those members is available upstream as DeclaredEditPlan, and this
crate deliberately does not use it. Plan annotations live in undeclared
members, and the crate’s own evidence budget and reserved-key checks walk the
extension maps, so a declared-only decode here would be a validation bypass
rather than an optimization: an oversized annotation blob that is rejected
today would pass. tests/declared_decode.rs pins that, and
docs/benchmarks.md records the decision.
The product route this crate exists for, validating a plan and binding it to a canonical fingerprint, is 3.3x faster at that size and 2.4x on the conservative gate.
A row states a “≥2.0x” claim only when its scope is declared equal and its
conservative ratio clears 2.0; stronger or mismatched scopes stay ineligible
regardless of ratio, and losing rows stay visible. This is not a universal
ranking. The harness, policy, and raw samples live in
tools/benchmarks and docs/benchmarks.md.
§MSRV and license
Rust 1.88 or newer, edition 2024. MIT licensed.
Re-exports§
pub use weavatrix_edit;
Structs§
- Apply
Limits - Bounded in-memory application limits for one source file.
- Batch
Limits - Hard resource limits for incrementally building one original-source batch.
- Borrowed
File Edit - Zero-copy view of one exact file edit set.
- Completeness
- Completeness claim made by a planner.
- Completeness
Proof - Typed proof identifying both the measured scope and its producer.
- Create
File - Exact UTF-8 contents to create at a path that must be absent.
- Create
Permissions - Deterministic portable permission policy for a newly created source file.
- Delete
File - Delete an existing file only when its complete contents match.
- Edit
Error - A fail-closed validation or application error.
- Edit
Plan - Versioned, extensible multi-file edit-plan envelope.
- Edit
Validation Stats - Owned statistics produced by zero-copy file-edit validation.
- Evidence
Scope - Machine-comparable scope covered by a completeness claim.
- File
Edit - All edits for one repository-relative UTF-8 source file.
- Fingerprint
Parse Error - An invalid encoded plan fingerprint.
- Line
Index Limits - Resource limits for building a reusable full
crate::LineIndex. - NotModified
- One intentionally omitted change with an evidence-backed explanation.
- Plan
Error - A bounded, fail-closed plan profile error.
- Plan
Evidence - Typed evidence flattened into the top-level refactor-plan object.
- Plan
Fingerprint - A SHA-256 fingerprint over the validated JCS refactor-plan contract.
- Plan
Limits - Bounded validation limits for a multi-file edit plan.
- Plan
Stats - Bounded statistics established by structural validation.
- Planner
Identity - Planner and backend identity behind a completeness claim.
- Position
- A 1-based line and 0-based UTF-16 code-unit position.
- Provenance
- Evidence tier attached to an exact source edit.
- Refactor
Plan - A bounded, versioned collection of logical refactor operations and evidence.
- Refactor
Plan Limits - Hard ceilings applied before a refactor plan can be fingerprinted or executed.
- Rename
File - Move one exact source to an absent destination.
- Scope
Kind - An open kind code for a completeness-proof scope.
- Status
Code - An open result-status code shared by planner and later workflow result models.
- Subject
Kind - An open kind code for an evidence subject.
- Text
Edit - One exact replacement over the original source text.
- Text
Range - A half-open source range.
- Typed
Subject - A typed symbol, resource, declaration, or other evidence subject.
- Uncertain
Reference - One explicitly unproven or uncovered reference.
- Uncertainty
Code - An open uncertainty kind or reason code.
- Validated
Consumer Plan - A consumer-compatible plan proven structurally safe and internally consistent.
- Validated
Edit Plan - Proof that an edit plan passed structural, evidence, path, and budget checks.
- Validated
Executor Plan - Exact-operation executor input, independent of semantic completeness.
- Validated
Planner Plan - Strict producer output with explicit, truthful completeness evidence.
- Warning
Code - An open warning code. Unknown future warnings remain representable.
- Write
Summary - Metadata returned after a prepared result is fully written.
Enums§
- Error
Code - Stable machine-readable failure categories.
- Graph
Revision - A graph revision preserving missing, explicit JSON null, and string states.
- Plan
Error Code - Stable categories for refactor-plan profile failures.
- Position
Encoding - Character-unit convention used for line/character conversion.
- Refactor
Operation - One logical operation in a refactor plan.
Constants§
- EDIT_
PLAN_ SCHEMA - Frozen JSON contract consumed by Weavatrix Refactor.
- FILE_
EDIT_ RESERVED_ EXTENSION_ KEYS - Reserved JSON member names for a
FileEditextension map. - FINGERPRINT_
ALGORITHM - Versioned algorithm identifier included as the fingerprint domain separator.
- MAX_
PLAN_ OPERATION_ BYTES - Absolute UTF-8 byte ceiling for a caller-defined operation label.
- REFACTOR_
PLAN_ SCHEMA - Stable wire schema owned by this crate.
- VERSION
- This crate’s package version.
Functions§
- apply_
edits_ with_ limits - Validates and applies v1 UTF-16 edits with explicit resource limits.
- attach_
annotations - Attaches typed evidence to a legacy edit plan without overwriting fields.
- canonical_
plan_ bytes - Validates with default limits and returns JCS bytes excluding top-level
createdAt. - canonical_
plan_ bytes_ with_ limits - Validates with caller limits and returns the canonical fingerprint payload.
- detach_
annotations - Removes all legacy top-level extensions and decodes them as evidence.
- extract_
annotations - Reads typed evidence from a legacy edit plan without changing it.
- fingerprint_
plan - Computes a validated, domain-separated JCS fingerprint with default limits.
- fingerprint_
plan_ with_ limits - Computes a validated, domain-separated JCS fingerprint with caller limits.
- parse_
refactor_ plan - Parses, duplicate-checks, bounds, and validates one refactor-plan document.
- portable_
path_ key - Conservative portable identity with Unicode canonical-equivalence folding.
- prepare_
edits_ with_ limits - Prepares v1 UTF-16 edits with explicit resource limits.
- replace_
annotations - Replaces legacy edit-plan evidence while preserving frozen edit fields.
- validate_
consumer_ plan - Validates exact operations and any recognized evidence that is present.
- validate_
edit_ plan - Validates a frozen edit-plan envelope and its borrowed file/edit contents.
- validate_
executor_ plan - Validates filesystem-safe exact operations without requiring COMPLETE semantics.
- validate_
file_ edits - Validates arbitrary borrowed file edits with the same engine as
EditPlan. - validate_
plan_ path - Validates a portable repository-relative refactor target.
- validate_
planner_ plan - Validates a strict planner-produced plan with explicit evidence.
Type Aliases§
- Plan
Annotations - Compatibility name for the evidence type used by the former annotation API.
- Validated
Refactor Plan - Compatibility name for the general validated refactor-plan wrapper.