Skip to main content

Crate weavatrix_refactor_plan

Crate weavatrix_refactor_plan 

Source
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-worktree

weavatrix-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 original from source, 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:

  • EvidenceScope has an open kind, a stable value, optional portable roots, and languages;
  • PlannerIdentity identifies planner name/version and backend, with an optional backend version;
  • graphRevision preserves missing, explicit null, 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 3339 createdAt, explicit graphRevision, 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, .git and .weavatrix exclusion, 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 to Modify and preserves completeness and every top-level extension;
  • try_into_text_edit_plan succeeds only when every operation is Modify.

The lower-level crate is also available as weavatrix_refactor_plan::weavatrix_edit.

§Conformance evidence

  • docs/schema/weavatrix.refactor-plan.profile.v1.schema.json describes the strict producer profile and all four operation values.
  • tests/fixtures/refactor-plan-v1.jsonl contains Node-generated canonical JCS payloads and fingerprints checked by Rust.
  • tests/fixtures/generate-refactor-plan-v1.mjs is the independent Node oracle.
  • tests/fixtures/refactor-plan-conformance.jsonl binds raw JSON cases to the runtime consumer/planner results.
  • tests/fixtures/js-v0.1.5-ownership.json accounts 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.

Class500-file plan, JS -> Rust medianConservative ratioScope
Cached fingerprint lookup0.005 -> 0.000 µs11.19xEqual semantics
End-to-end validate + fingerprint3570 -> 1092 µs2.44xRust validates strictly more
Legacy envelope validation370 -> 233 µs1.27xEqual declared subset
Parse + legacy validation855 -> 1018 µs0.65xEqual 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§

ApplyLimits
Bounded in-memory application limits for one source file.
BatchLimits
Hard resource limits for incrementally building one original-source batch.
BorrowedFileEdit
Zero-copy view of one exact file edit set.
Completeness
Completeness claim made by a planner.
CompletenessProof
Typed proof identifying both the measured scope and its producer.
CreateFile
Exact UTF-8 contents to create at a path that must be absent.
CreatePermissions
Deterministic portable permission policy for a newly created source file.
DeleteFile
Delete an existing file only when its complete contents match.
EditError
A fail-closed validation or application error.
EditPlan
Versioned, extensible multi-file edit-plan envelope.
EditValidationStats
Owned statistics produced by zero-copy file-edit validation.
EvidenceScope
Machine-comparable scope covered by a completeness claim.
FileEdit
All edits for one repository-relative UTF-8 source file.
FingerprintParseError
An invalid encoded plan fingerprint.
LineIndexLimits
Resource limits for building a reusable full crate::LineIndex.
NotModified
One intentionally omitted change with an evidence-backed explanation.
PlanError
A bounded, fail-closed plan profile error.
PlanEvidence
Typed evidence flattened into the top-level refactor-plan object.
PlanFingerprint
A SHA-256 fingerprint over the validated JCS refactor-plan contract.
PlanLimits
Bounded validation limits for a multi-file edit plan.
PlanStats
Bounded statistics established by structural validation.
PlannerIdentity
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.
RefactorPlan
A bounded, versioned collection of logical refactor operations and evidence.
RefactorPlanLimits
Hard ceilings applied before a refactor plan can be fingerprinted or executed.
RenameFile
Move one exact source to an absent destination.
ScopeKind
An open kind code for a completeness-proof scope.
StatusCode
An open result-status code shared by planner and later workflow result models.
SubjectKind
An open kind code for an evidence subject.
TextEdit
One exact replacement over the original source text.
TextRange
A half-open source range.
TypedSubject
A typed symbol, resource, declaration, or other evidence subject.
UncertainReference
One explicitly unproven or uncovered reference.
UncertaintyCode
An open uncertainty kind or reason code.
ValidatedConsumerPlan
A consumer-compatible plan proven structurally safe and internally consistent.
ValidatedEditPlan
Proof that an edit plan passed structural, evidence, path, and budget checks.
ValidatedExecutorPlan
Exact-operation executor input, independent of semantic completeness.
ValidatedPlannerPlan
Strict producer output with explicit, truthful completeness evidence.
WarningCode
An open warning code. Unknown future warnings remain representable.
WriteSummary
Metadata returned after a prepared result is fully written.

Enums§

ErrorCode
Stable machine-readable failure categories.
GraphRevision
A graph revision preserving missing, explicit JSON null, and string states.
PlanErrorCode
Stable categories for refactor-plan profile failures.
PositionEncoding
Character-unit convention used for line/character conversion.
RefactorOperation
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 FileEdit extension 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§

PlanAnnotations
Compatibility name for the evidence type used by the former annotation API.
ValidatedRefactorPlan
Compatibility name for the general validated refactor-plan wrapper.