Add regex command implementation

This commit is contained in:
Rogee
2025-10-31 10:12:02 +08:00
parent a0d7084c28
commit d436970848
55 changed files with 2115 additions and 9 deletions

View File

@@ -0,0 +1,34 @@
# Specification Quality Checklist: Regex Command for Pattern-Based Renaming
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2025-10-30
**Feature**: specs/001-add-regex-command/spec.md
## Content Quality
- [X] No implementation details (languages, frameworks, APIs)
- [X] Focused on user value and business needs
- [X] Written for non-technical stakeholders
- [X] All mandatory sections completed
## Requirement Completeness
- [X] No [NEEDS CLARIFICATION] markers remain
- [X] Requirements are testable and unambiguous
- [X] Success criteria are measurable
- [X] Success criteria are technology-agnostic (no implementation details)
- [X] All acceptance scenarios are defined
- [X] Edge cases are identified
- [X] Scope is clearly bounded
- [X] Dependencies and assumptions identified
## Feature Readiness
- [X] All functional requirements have clear acceptance criteria
- [X] User scenarios cover primary flows
- [X] Feature meets measurable outcomes defined in Success Criteria
- [X] No implementation details leak into specification
## Notes
- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`

View File

@@ -0,0 +1,248 @@
openapi: 3.1.0
info:
title: Renamer Regex Command API
version: 0.1.0
description: >
Contract representation of the `renamer regex` command workflows (preview/apply/undo)
for automation harnesses and documentation parity.
servers:
- url: cli://renamer
description: Command-line invocation surface
paths:
/regex/preview:
post:
summary: Preview regex-based rename results
description: Mirrors `renamer regex <pattern> <template> --dry-run`
operationId: previewRegex
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegexRequest'
responses:
'200':
description: Successful preview
content:
application/json:
schema:
$ref: '#/components/schemas/RegexPreview'
'400':
description: Validation error (invalid pattern, undefined placeholders)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/regex/apply:
post:
summary: Apply regex-based renaming
description: Mirrors `renamer regex <pattern> <template> --yes`
operationId: applyRegex
requestBody:
required: true
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/RegexRequest'
- type: object
properties:
dryRun:
type: boolean
const: false
responses:
'200':
description: Apply succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/RegexApplyResult'
'409':
description: Conflict detected (duplicate targets, existing files)
content:
application/json:
schema:
$ref: '#/components/schemas/ConflictResponse'
'400':
description: Validation error (invalid pattern/template)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/regex/undo:
post:
summary: Undo the latest regex rename batch
description: Mirrors `renamer undo` when the last ledger entry corresponds to a regex command.
operationId: undoRegex
responses:
'200':
description: Undo succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/UndoResult'
'409':
description: Ledger inconsistent or no regex entry found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
RegexRequest:
type: object
required:
- workingDir
- pattern
- template
properties:
workingDir:
type: string
pattern:
type: string
description: RE2-compatible regular expression applied to filename stem.
template:
type: string
description: Replacement template supporting placeholders `@0..@n`.
includeDirs:
type: boolean
default: false
recursive:
type: boolean
default: false
includeHidden:
type: boolean
default: false
extensionFilter:
type: array
items:
type: string
dryRun:
type: boolean
default: true
autoConfirm:
type: boolean
default: false
RegexPreview:
type: object
required:
- totalCandidates
- matched
- changed
- entries
properties:
totalCandidates:
type: integer
minimum: 0
matched:
type: integer
minimum: 0
changed:
type: integer
minimum: 0
skipped:
type: integer
minimum: 0
conflicts:
type: array
items:
$ref: '#/components/schemas/Conflict'
warnings:
type: array
items:
type: string
entries:
type: array
items:
$ref: '#/components/schemas/PreviewEntry'
RegexApplyResult:
type: object
required:
- totalApplied
- skipped
- ledgerEntryId
properties:
totalApplied:
type: integer
minimum: 0
skipped:
type: integer
minimum: 0
ledgerEntryId:
type: string
warnings:
type: array
items:
type: string
UndoResult:
type: object
required:
- restored
- ledgerEntryId
properties:
restored:
type: integer
ledgerEntryId:
type: string
message:
type: string
Conflict:
type: object
required:
- originalPath
- proposedPath
- reason
properties:
originalPath:
type: string
proposedPath:
type: string
reason:
type: string
enum:
- duplicate_target
- existing_file
- existing_directory
- invalid_template
PreviewEntry:
type: object
required:
- originalPath
- proposedPath
- status
properties:
originalPath:
type: string
proposedPath:
type: string
status:
type: string
enum:
- changed
- no_change
- skipped
matchGroups:
type: array
items:
type: string
ErrorResponse:
type: object
required:
- error
properties:
error:
type: string
remediation:
type: string
ConflictResponse:
type: object
required:
- error
- conflicts
properties:
error:
type: string
conflicts:
type: array
items:
$ref: '#/components/schemas/Conflict'

View File

@@ -0,0 +1,62 @@
# Data Model Regex Command
## Entity: RegexRequest
- **Fields**
- `WorkingDir string` — Absolute path derived from CLI `--path` or current directory.
- `Pattern string` — User-supplied regular expression.
- `Template string` — Replacement string with `@n` placeholders.
- `IncludeDirs bool` — Mirrors `--include-dirs` flag.
- `Recursive bool` — Mirrors `--recursive` flag.
- `IncludeHidden bool` — True only when `--hidden` is supplied.
- `ExtensionFilter []string` — Filter tokens from `--extensions`.
- `DryRun bool` — Preview-only execution state.
- `AutoConfirm bool` — Captures `--yes` for non-interactive runs.
- `Timestamp time.Time` — Invocation timestamp for ledger correlation.
- **Validation Rules**
- Regex must compile; invalid patterns produce errors.
- Template may reference `@0` (full match) and numbered groups; referencing undefined groups is invalid.
- Prohibit control characters and path separators in resulting names.
- **Relationships**
- Consumed by regex engine to build rename plan.
- Serialized into ledger metadata alongside summary output.
## Entity: RegexSummary
- **Fields**
- `TotalCandidates int` — Items inspected after scope filtering.
- `Matched int` — Files whose names matched the regex.
- `Changed int` — Entries that will change after template substitution.
- `Skipped int` — Non-matching or invalid-template entries.
- `Conflicts []Conflict` — Rename collisions or generated duplicates.
- `Warnings []string` — Validation notices (unused groups, truncated templates).
- `Entries []PreviewEntry` — Original/proposed mappings with status.
- `LedgerMetadata map[string]any` — Snapshot persisted with ledger entry (pattern, template, scope flags).
- **Validation Rules**
- Conflicts must be empty before apply.
- `Matched = Changed + (matched entries with no change)` for consistency.
- **Relationships**
- Drives preview rendering.
- Input for ledger writer and undo verification.
## Entity: Conflict
- **Fields**
- `OriginalPath string`
- `ProposedPath string`
- `Reason string` — (`duplicate_target`, `existing_file`, `invalid_template`).
- **Validation Rules**
- `ProposedPath` unique among planned operations.
- Reason drawn from known enum for consistent messaging.
- **Relationships**
- Reported in preview output and blocks apply.
## Entity: PreviewEntry
- **Fields**
- `OriginalPath string`
- `ProposedPath string`
- `Status string``changed`, `no_change`, `skipped`.
- `MatchGroups []string` — Captured groups applied to template.
- **Validation Rules**
- `ProposedPath` equals `OriginalPath` when `Status == "no_change"`.
- `MatchGroups` length must equal number of captured groups.
- **Relationships**
- Displayed in preview output.
- Persisted alongside ledger metadata for undo.

View File

@@ -0,0 +1,96 @@
# Implementation Plan: Regex Command for Pattern-Based Renaming
**Branch**: `006-add-regex-command` | **Date**: 2025-10-30 | **Spec**: `specs/006-add-regex-command/spec.md`
**Input**: Feature specification from `/specs/006-add-regex-command/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
## Summary
Deliver a `renamer regex` subcommand that compiles a user-supplied pattern, substitutes numbered capture groups into a replacement template, surfaces deterministic previews, and records ledger metadata so undo and automation workflows remain safe and auditable.
## Technical Context
**Language/Version**: Go 1.24
**Primary Dependencies**: `spf13/cobra`, `spf13/pflag`, Go `regexp` (RE2 engine), internal traversal/history/output packages
**Storage**: Local filesystem and `.renamer` ledger files
**Testing**: `go test ./...`, contract suites under `tests/contract`, integration flows under `tests/integration`, targeted smoke script
**Target Platform**: Cross-platform CLI (Linux, macOS, Windows shells)
**Project Type**: Single CLI project (`cmd/`, `internal/`, `tests/`, `scripts/`)
**Performance Goals**: Preview + apply 500 regex-driven renames in <2 minutes end-to-end
**Constraints**: Preview-first confirmation, reversible ledger entries, Unicode-safe regex evaluation, conflict detection before apply
**Scale/Scope**: Expected to operate on thousands of entries per invocation within local directories
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- Preview flow MUST show deterministic rename mappings and require explicit confirmation (Preview-First Safety). ✅ Use shared preview renderer to list original → proposed names plus skipped/conflict indicators prior to apply.
- Undo strategy MUST describe how the `.renamer` ledger entry is written and reversed (Persistent Undo Ledger). ✅ Append ledger entries containing pattern, template, captured groups per file, enabling `renamer undo` to restore originals.
- Planned rename rules MUST document their inputs, validations, and composing order (Composable Rule Engine). ✅ Build a dedicated regex rule that compiles patterns, validates templates, and plugs into traversal pipeline without altering shared state.
- Scope handling MUST cover files vs directories (`-d`), recursion (`-r`), and extension filtering via `-e` without escaping the requested path (Scope-Aware Traversal). ✅ Reuse traversal filters so regex respects directory, recursion, hidden, and extension flags identically to other commands.
- CLI UX plan MUST confirm Cobra usage, flag naming, help text, and automated tests for preview/undo flows (Ergonomic CLI Stewardship). ✅ Add Cobra subcommand with documented flags, examples, help output, and contract/integration coverage for preview/apply/undo flows.
*Post-Design Verification (2025-10-30): Research, data model, contracts, and quickstart documents confirm preview coverage, ledger metadata, regex template validation, and CLI UX updates — no gate violations detected.*
## Project Structure
### Documentation (this feature)
```text
specs/006-add-regex-command/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md # Generated via /speckit.tasks
```
### Source Code (repository root)
```text
cmd/
├── root.go
├── list.go
├── replace.go
├── remove.go
├── extension.go
├── insert.go
├── regex.go # NEW
└── undo.go
internal/
├── filters/
├── history/
├── listing/
├── output/
├── remove/
├── replace/
├── extension/
├── insert/
└── regex/ # NEW: pattern compilation, template evaluation, engine, ledger metadata
tests/
├── contract/
├── integration/
├── fixtures/
└── unit/
scripts/
├── smoke-test-list.sh
├── smoke-test-replace.sh
├── smoke-test-remove.sh
├── smoke-test-extension.sh
├── smoke-test-insert.sh
└── smoke-test-regex.sh # NEW
```
**Structure Decision**: Extend the single CLI project by introducing `cmd/regex.go`, a new `internal/regex` package for rule evaluation, and corresponding contract/integration tests plus a smoke script under existing directories.
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|

View File

@@ -0,0 +1,28 @@
# Quickstart Regex Command
1. **Preview a capture-group rename before applying.**
```bash
renamer regex '^(\d{4})-(\d{2})_(.*)$' 'Q@2-@1_@3' --dry-run
```
- Converts `2025-01_report.txt` into `Q01-2025_report.txt` in preview mode.
- Skipped files remain untouched and are labeled in the preview table.
2. **Limit scope with extension and directory flags.**
```bash
renamer regex '^(build)_(\d+)_v(.*)$' 'release-@2-@1-v@3' --path ./artifacts --extensions .zip|.tar.gz --include-dirs --dry-run
```
- Applies only to archives under `./artifacts`, including subdirectories when paired with `-r`.
- Hidden files remain excluded unless `--hidden` is added.
3. **Apply changes non-interactively for automation.**
```bash
renamer regex '^(feature)-(.*)$' '@2-@1' --yes --path ./staging
```
- `--yes` confirms using the preview plan and writes a ledger entry containing pattern and template metadata.
- Exit code `0` indicates success; non-zero signals validation or conflict issues.
4. **Undo the last regex batch if results are unexpected.**
```bash
renamer undo --path ./staging
```
- Restores original filenames using the `.renamer` ledger captured during apply.

View File

@@ -0,0 +1,21 @@
# Phase 0 Research Regex Command
## Decision: Reuse Traversal, Preview, and Ledger Pipelines for Regex Rule
- **Rationale**: Existing replace/remove/extension commands already walk the filesystem, apply scope filters, and feed preview + ledger writers. Plugging a regex rule into this pipeline guarantees consistent conflict detection, skipped reporting, and undo safety without reimplementing traversal safeguards.
- **Alternatives considered**: Building a standalone regex walker was rejected because it would duplicate scope logic and risk violating Scope-Aware Traversal. Embedding regex into replace internals was rejected to keep literal and regex behaviors independent and easier to test.
## Decision: Compile Patterns with Go `regexp` (RE2) and Cache Group Metadata
- **Rationale**: Gos standard library provides RE2-backed regex compilation with deterministic performance and Unicode safety. Capturing the compiled expression once per invocation lets us pre-count capture groups, validate templates, and apply matches efficiently across many files.
- **Alternatives considered**: Using third-party regex engines (PCRE) was rejected due to external dependencies and potential catastrophic backtracking. Recompiling the pattern per file was rejected for performance reasons.
## Decision: Validate and Render Templates via Placeholder Tokens (`@0`, `@1`, …, `@@`)
- **Rationale**: Parsing the template into literal and placeholder segments ensures undefined group references surface as validation errors before preview/apply, while optional groups that fail to match substitute with empty strings. Doubling `@` (i.e., `@@`) yields a literal `@`, aligning with the clarification already captured in the specification.
- **Alternatives considered**: Allowing implicit zero-value substitution for undefined groups was rejected because it hides mistakes. Relying on `fmt.Sprintf`-style formatting was rejected since it lacks direct mapping to numbered capture groups and complicates escaping rules.
## Decision: Ledger Metadata Includes Pattern, Template, and Match Snapshots
- **Rationale**: Persisting the regex pattern, replacement template, scope flags, and per-file capture arrays alongside old/new paths enables precise undo and supports automation auditing. This mirrors expectations set for other commands and satisfies the Persistent Undo Ledger principle.
- **Alternatives considered**: Logging only before/after filenames was rejected because undo would lose context if filenames changed again outside the tool. Capturing full file contents was rejected as unnecessary and intrusive.
## Decision: Block Apply When Template Yields Conflicts or Empty Targets
- **Rationale**: Conflict detection will reuse existing duplicate/overwrite checks but extend them to treat empty or whitespace-only proposals as invalid. Apply exits non-zero when conflicts remain, protecting against accidental data loss or invalid filenames.
- **Alternatives considered**: Auto-resolving conflicts by suffixing counters was rejected because it introduces nondeterministic results and complicates undo. Allowing empty targets was rejected for safety and compatibility reasons.

View File

@@ -0,0 +1,107 @@
# Feature Specification: Regex Command for Pattern-Based Renaming
**Feature Branch**: `006-add-regex-command`
**Created**: 2025-10-30
**Status**: Draft
**Input**: User description: "实现 regex 命令,用于使用正则获取指定位置内容后再重新命名,示例 renamer regexp <pattern> @1-@2 实现了获取正则的第一、二位的匹配数据,并进行重新命名"
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Rename Files Using Captured Groups (Priority: P1)
As a power user organizing datasets, I want to rename files by extracting portions of their names via regular expressions so that I can normalize naming schemes without writing custom scripts.
**Why this priority**: Provides the core value—regex-driven renaming to rearrange captured data quickly across large batches.
**Independent Test**: In a directory with files named `2025-01_report.txt` and `2025-02_report.txt`, run `renamer regex "^(\\d{4})-(\\d{2})_report" "Q@2-@1" --dry-run` and verify the preview shows `Q01-2025.txt` and `Q02-2025.txt`. Re-run with `--yes` to confirm filesystem updates and ledger entry.
**Acceptance Scenarios**:
1. **Given** files `alpha-123.log` and `beta-456.log`, **When** the user runs `renamer regex "^(\\w+)-(\\d+)" "@2_@1" --dry-run`, **Then** the preview lists `123_alpha.log` and `456_beta.log` as proposed names.
2. **Given** files that do not match the pattern, **When** the command runs in preview mode, **Then** unmatched files are listed with a "skipped" status and no filesystem changes occur on apply.
---
### User Story 2 - Automation-Friendly Regex Renames (Priority: P2)
As a DevOps engineer automating release artifact naming, I need deterministic exit codes, ledger metadata, and undo support for regex-based renames so CI pipelines remain auditable and reversible.
**Why this priority**: Ensures the new command can be safely adopted in automation without risking opaque failures.
**Independent Test**: Execute `renamer regex "^build_(\\d+)_(.*)$" "release-@1-@2" --yes --path ./fixtures`, verify exit code `0`, inspect `.renamer` for recorded pattern, replacement template, and affected files, then run `renamer undo` to restore originals.
**Acceptance Scenarios**:
1. **Given** a non-interactive run with `--yes`, **When** all matches succeed without conflicts, **Then** exit code is `0` and the ledger entry records the regex pattern, replacement template, and matching groups per file.
2. **Given** a ledger entry produced by `renamer regex`, **When** `renamer undo` executes, **Then** filenames revert to their previous values even if the original files contained Unicode characters or were renamed by automation.
---
### User Story 3 - Validate Patterns, Placeholders, and Conflicts (Priority: P3)
As a user experimenting with regex templates, I want clear validation and preview feedback for invalid patterns, missing capture groups, or resulting conflicts so I can adjust commands before committing changes.
**Why this priority**: Prevents accidental data loss and reduces trial-and-error when constructing regex commands.
**Independent Test**: Run `renamer regex "^(.*)$" "@2" --dry-run` and confirm the command exits with a descriptive error because placeholder `@2` is undefined; run a scenario where multiple files would map to the same name and ensure apply is blocked.
**Acceptance Scenarios**:
1. **Given** a replacement template referencing an undefined capture group, **When** the command runs, **Then** it exits non-zero with a message explaining the missing group and no files change.
2. **Given** two files whose matches produce identical targets, **When** preview executes, **Then** conflicts are listed and apply refuses to proceed until resolved.
---
### Edge Cases
- How does the command behave when the regex pattern is invalid or cannot compile?
- What is the outcome when no files match the pattern (preview and apply)?
- How are nested or optional groups handled when placeholders reference non-matching groups?
- What happens if the replacement template results in empty filenames or removes extensions?
- How are directories or hidden files treated when scope flags include/exclude them?
- What feedback is provided when resulting names differ only by case on case-insensitive filesystems?
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: CLI MUST provide a `regex` subcommand that accepts a required regex pattern and replacement template arguments (e.g., `renamer regex <pattern> <template>`).
- **FR-002**: Replacement templates MUST support numbered capture placeholders (`@1`, `@2`, etc.) corresponding to the regex groups; referencing undefined groups MUST produce a validation error.
- **FR-003**: Pattern matching MUST operate on the filename stem by default while preserving extensions unless the template explicitly alters them.
- **FR-004**: Preview MUST display original names, proposed names, and highlight skipped entries (unmatched, invalid template) prior to apply; apply MUST be blocked when conflicts or validation errors exist.
- **FR-005**: Execution MUST respect shared scope flags (`--path`, `--recursive`, `--include-dirs`, `--hidden`, `--extensions`, `--dry-run`, `--yes`) consistent with other commands.
- **FR-006**: Ledger entries MUST capture the regex pattern, replacement template, and affected files so undo can restore originals deterministically.
- **FR-007**: The command MUST emit deterministic exit codes: `0` for successful apply or no matches, non-zero for validation failures or conflicts.
- **FR-008**: Help output MUST document pattern syntax expectations, placeholder usage, escaping rules, and examples for both files and directories.
### Key Entities
- **RegexRequest**: Working directory, regex pattern, replacement template, scope flags, dry-run/apply settings.
- **RegexSummary**: Counts of matched files, skipped entries, conflicts, warnings, and preview entries with status (`changed`, `skipped`, `no_change`).
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: Users rename 500 files via regex (preview + apply) in under 2 minutes end-to-end.
- **SC-002**: 95% of beta testers correctly apply a regex rename after reading `renamer regex --help` without additional guidance.
- **SC-003**: Automated regression tests confirm regex rename + undo cycles leave the filesystem unchanged in 100% of scripted scenarios.
- **SC-004**: Support tickets related to custom regex renaming scripts drop by 30% within the first release cycle post-launch.
## Clarifications
### Session 2025-10-30
- Q: How should literal @ characters be escaped in templates? → A: Use @@ to emit a literal @ while keeping numbered placeholders intact.
## Assumptions
- Regex evaluation uses the runtimes built-in engine with RE2-compatible syntax; no backtracking-specific constructs (e.g., look-behind) are supported.
- Matching applies to filename stems by default; users can reconstruct extensions via placeholders if required.
- Unmatched files are skipped gracefully and reported in preview; apply exits `0` when all files are skipped.
- Templates treat `@0` as the entire match if referenced; placeholders are case-sensitive and must be preceded by `@`. Use `@@` to emit a literal `@` character.
## Dependencies & Risks
- Requires extending existing traversal, preview, and ledger infrastructure to accommodate regex replacement logic.
- Complex regex patterns may produce unexpected duplicates; conflict detection must guard against accidental overwrites.
- Users may expect advanced regex features (named groups, non-ASCII classes); documentation must clarify supported syntax to prevent confusion.

View File

@@ -0,0 +1,159 @@
# Tasks: Regex Command for Pattern-Based Renaming
**Input**: Design documents from `/specs/006-add-regex-command/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
**Tests**: Include targeted contract and integration coverage where scenarios demand automated verification.
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
## Format: `[ID] [P?] [Story] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Prepare fixtures and support tooling required across all stories.
- [X] T001 Create regex test fixtures (`tests/fixtures/regex/`) with sample filenames covering digits, words, and Unicode cases.
- [X] T002 [P] Scaffold `scripts/smoke-test-regex.sh` mirroring quickstart scenarios for preview/apply/undo.
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Establish reusable package skeletons and command registration that all stories build upon.
- [X] T003 Create `internal/regex` package scaffolding (request.go, summary.go, doc.go) matching data-model entities.
- [X] T004 [P] Register a stub `regex` Cobra command in `cmd/regex.go` with flag definitions aligned to shared scope options.
**Checkpoint**: Foundation ready user story implementation can now begin.
---
## Phase 3: User Story 1 - Rename Files Using Captured Groups (Priority: P1) 🎯 MVP
**Goal**: Allow users to preview regex-based renames that substitute captured groups into templates while preserving extensions.
**Independent Test**: Run `renamer regex "^(\w+)-(\d+)" "@2_@1" --dry-run` against fixtures and verify preview outputs `123_alpha.log`, `456_beta.log` without modifying the filesystem.
### Tests for User Story 1
- [X] T005 [P] [US1] Add preview contract test for capture groups in `tests/contract/regex_command_test.go`.
- [X] T006 [P] [US1] Add integration preview flow test covering dry-run confirmation in `tests/integration/regex_flow_test.go`.
### Implementation for User Story 1
- [X] T007 [P] [US1] Implement template parser handling `@n` and `@@` tokens in `internal/regex/template.go`.
- [X] T008 [P] [US1] Implement regex engine applying capture groups to candidate names in `internal/regex/engine.go`.
- [X] T009 [US1] Build preview planner producing `RegexSummary` entries in `internal/regex/preview.go`.
- [X] T010 [US1] Wire Cobra command to preview/apply planner with scope options in `cmd/regex.go`.
**Checkpoint**: User Story 1 preview capability ready for validation.
---
## Phase 4: User Story 2 - Automation-Friendly Regex Renames (Priority: P2)
**Goal**: Deliver deterministic apply flows with ledger metadata and undo support suitable for CI automation.
**Independent Test**: Execute `renamer regex "^build_(\d+)_(.*)$" "release-@1-@2" --yes --path ./tests/fixtures/regex` and verify exit code `0`, ledger metadata, and successful `renamer undo` restoration.
### Tests for User Story 2
- [X] T011 [P] [US2] Add ledger contract test capturing pattern/template metadata in `tests/contract/regex_ledger_test.go`.
- [X] T012 [P] [US2] Add integration undo flow test for regex entries in `tests/integration/regex_undo_test.go`.
### Implementation for User Story 2
- [X] T013 [P] [US2] Implement apply handler persisting ledger entries in `internal/regex/apply.go`.
- [X] T014 [US2] Ensure `cmd/regex.go` honors `--yes` automation semantics and deterministic exit codes.
- [X] T015 [US2] Extend undo recognition for regex batches in `internal/history/history.go` and shared output messaging.
**Checkpoint**: Automation-focused workflows (apply + undo) validated.
---
## Phase 5: User Story 3 - Validate Patterns, Placeholders, and Conflicts (Priority: P3)
**Goal**: Provide clear feedback for invalid patterns or template conflicts to prevent destructive applies.
**Independent Test**: Run `renamer regex "^(.*)$" "@2" --dry-run` and confirm an error about undefined capture groups; attempt a rename producing duplicate targets and confirm apply is blocked.
### Tests for User Story 3
- [X] T016 [P] [US3] Add validation contract tests for invalid patterns/placeholders in `tests/contract/regex_validation_test.go`.
- [X] T017 [P] [US3] Add integration conflict test ensuring duplicate targets block apply in `tests/integration/regex_conflict_test.go`.
### Implementation for User Story 3
- [X] T018 [P] [US3] Implement validation for undefined groups and empty results in `internal/regex/validate.go`.
- [X] T019 [US3] Extend conflict detection to flag duplicate or empty proposals in `internal/regex/preview.go`.
- [X] T020 [US3] Enhance CLI error messaging and help examples in `cmd/regex.go`.
**Checkpoint**: Validation safeguards complete; regex command safe for experimentation.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Final documentation, tooling, and quality passes.
- [X] T021 [P] Update CLI documentation with regex command details in `docs/cli-flags.md`.
- [X] T022 [P] Finalize `scripts/smoke-test-regex.sh` to exercise quickstart scenarios and ledger undo.
- [X] T023 Run `gofmt` and `go test ./...` to verify formatting and regression coverage.
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)** → prerequisite for foundational work.
- **Foundational (Phase 2)** → must complete before User Stories begin.
- **User Stories (Phase 35)** → execute sequentially by priority or in parallel once dependencies satisfied.
- **Polish (Phase 6)** → runs after desired user stories ship.
### User Story Dependencies
- **US1** depends on Foundational package scaffolding (T003T004).
- **US2** depends on US1 preview/apply wiring.
- **US3** depends on US1 preview engine and US2 apply infrastructure to validate.
### Parallel Opportunities
- Tasks marked `[P]` operate on distinct files and can proceed concurrently once their prerequisites are met.
- Different user stories can progress in parallel after their dependencies complete, provided shared files (`cmd/regex.go`, `internal/regex/preview.go`) are coordinated sequentially.
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 12 to establish scaffolding.
2. Implement US1 preview workflow (T005T010) and validate independently.
3. Ship preview-only capability if automation support can follow later.
### Incremental Delivery
1. Deliver US1 preview/apply basics.
2. Layer US2 automation + ledger features.
3. Add US3 validation/conflict safeguards.
4. Conclude with polish tasks for docs, smoke script, and regression suite.
### Parallel Team Strategy
- Developer A focuses on template/engine internals (T007T008) while Developer B builds tests (T005T006).
- After US1, split automation work: ledger implementation (T013) and undo validation tests (T012) run concurrently.
- Validation tasks (T016T020) can be parallelized between CLI messaging and conflict handling once US2 merges.
---
## Notes
- Keep task granularity small enough for independent completion while documenting file paths for each change.
- Tests should fail before implementation to confirm coverage.
- Mark tasks complete (`[X]`) in this document as work progresses.