Skip to main content
rename and move are your safe refactoring commands. They rewrite every reference across the workspace atomically, append an entry to the journal so that future identity mapping works correctly, and regenerate all derived files. If anything would leave the workspace in an invalid state, both commands refuse and exit 1 without touching any file.

xspec rename

rename changes a requirement ID within a source file, then propagates the change everywhere that ID is referenced.
path
required
Workspace-relative path to the spec file containing the ID to rename.
string
required
The existing ID to rename, expressed as the bare ID (not path#id).
string
required
The replacement ID. Must be valid, must not collide with an existing ID, and must not violate structural rules (e.g., the new segment must be a valid child of the same parent).

What rename rewrites

  • The ID declaration in <file>
  • All descendant IDs that use the old ID as a prefix
  • Every d attribute, text(...) call, and TypeScript reference to the renamed node or its descendants, across the entire workspace
  • All review session items referencing the old identity

Journal entry

After rewriting, rename appends a rename record to the journal. This record lets impact and review create --base correctly map the old identity to the new one when comparing against historical baselines.

Refusal conditions

rename refuses and exits 1 when:
  • The new ID is syntactically invalid
  • The new ID would collide with an existing ID in the same file
  • The rename would break structural rules (e.g., invalid nesting)
  • The workspace does not currently pass build validation — you must have a clean build before renaming

xspec move

move has two forms: relocating an entire file, or extracting a section subtree to a new location.

File form

Relocates the entire source file from <old-file> to <new-file>. All IDs within the file are unchanged. Every cross-file reference to nodes in <old-file> is updated to use the new path.

Section form

Removes the section rooted at <id> from <file> and inserts it as the last child of the parent indicated by <target-file>#<new-id>’s parent path. If <target-file> does not yet exist, xspec creates it. All descendant IDs within the moved section are updated to reflect their new prefix. All references across the workspace are rewritten accordingly.

What both forms rewrite

  • Source files involved in the move
  • Every d attribute, text(...) call, and TypeScript reference to moved nodes, across the entire workspace
  • All review session items referencing moved identities

Journal contract

Both forms append a move record to the journal. The journal records the old and new identities (and path for the file form) so that impact and baseline-comparison commands can map identities across the change.

Refusal conditions

Both forms of move refuse and exits 1 when:
  • The move would introduce a dependency or import cycle
  • The workspace does not currently pass build validation
The file form additionally refuses when:
  • <new-file> already exists
The section form additionally refuses when:
  • The target parent node does not exist
  • The target parent is inside the subtree being moved (a node cannot become its own ancestor)
  • <target-file> is not a valid spec source path

Concurrency

Both rename and move are mutating commands and are mutually exclusive per workspace. If either is invoked while another mutating command is running, it exits immediately with code 2. All file writes are applied atomically in effect — you will never observe a partial rewrite.