Double-Lock safety harness

Updated Jun 22, 2026

All act commands pass through a "Double-Lock" safety harness before any changes are committed to the filesystem. This verification layer ensures that agent-generated modifications do not corrupt the codebase by introducing syntax errors or type mismatches.

Two-phase verification

The harness validates proposed edits in two sequential phases:

  1. Syntactic Lock: Each modified file is parsed to ensure it produces a valid syntax tree. Structural errors such as unbalanced braces, missing semicolons, or malformed declarations are caught at this stage. Files that fail parsing are rejected immediately, and the filesystem remains untouched.

  2. Semantic Lock: If the syntactic lock passes, the modified content is submitted to the configured language server. The daemon requests fresh diagnostics and compares them against the pre-edit baseline. Any new errors or high-severity warnings cause the semantic lock to fail. Only when both locks pass are the changes atomically written to disk.

In-memory application

Edits are first applied to in-memory copies of the affected files. The original content is preserved until both verification phases succeed. This allows the harness to reject problematic changes without leaving partially written files on disk.

Document sync notifications

The semantic lock now opens in-memory documents on the language server using textDocument/didOpen, applies updates with textDocument/didChange, and closes them with textDocument/didClose once diagnostics are collected. This lets the server validate the modified content at the real file URI without writing temporary files, so cross-file imports resolve as usual.

Atomic commits

When both locks pass, the harness writes each modified file atomically by creating a temporary file and renaming it into place. This guarantees that a crash or power loss during the commit phase does not leave files in a corrupted intermediate state.

Error reporting

When verification fails, the harness returns a structured error describing:

  • Lock phase: Whether the failure occurred during syntactic or semantic validation.
  • Affected files: Paths to the files that triggered the failure.
  • Locations: Optional line and column numbers pinpointing each issue.
  • Messages: Human-readable descriptions of what went wrong.

Agents can use this information to diagnose problems and regenerate corrected edits. The structured format also enables tooling to present failures in IDE integrations or CI pipelines.

Tree-sitter syntactic lock

The syntactic lock is powered by the weaver-syntax crate, which integrates Tree-sitter parsers for Rust, Python, and TypeScript. When validating a file, the lock parses the content and inspects the resulting syntax tree for ERROR nodes. Files containing structural errors—such as unbalanced braces, missing semicolons, or malformed declarations—are rejected before the semantic lock runs. Files with extensions not recognized by any configured parser are skipped (pass through) to avoid blocking edits to configuration files, documentation, or other non-code artefacts.

The validation reports each failure with:

  • Path: The file that failed validation.
  • Line and column: The position of the first syntax error.
  • Message: A human-readable description (typically "syntax error").

This fast, local check catches many common agent mistakes without needing to contact a language server.

Pattern matching and rewriting

The weaver-syntax crate also provides a structural pattern matching engine inspired by ast-grep. Patterns use metavariables ($VAR for single captures, $$$VAR for multiple) to match and capture portions of the syntax tree. This enables the future observe grep and act apply-rewrite commands to perform precise, AST-aware search and transformation across the codebase. The engine currently supports Rust, Python, and TypeScript.