feat: scaffold remove command foundations
This commit is contained in:
34
specs/003-add-remove-command/checklists/requirements.md
Normal file
34
specs/003-add-remove-command/checklists/requirements.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Specification Quality Checklist: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2025-10-29
|
||||
**Feature**: [spec.md](../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`
|
||||
68
specs/003-add-remove-command/contracts/remove-command.md
Normal file
68
specs/003-add-remove-command/contracts/remove-command.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# CLI Contract: `renamer remove`
|
||||
|
||||
## Command Synopsis
|
||||
|
||||
```bash
|
||||
renamer remove <pattern1> [pattern2 ...] [flags]
|
||||
```
|
||||
|
||||
### Global Flags (inherited from root command)
|
||||
- `--path <dir>` (defaults to current working directory)
|
||||
- `-r`, `--recursive`
|
||||
- `-d`, `--include-dirs`
|
||||
- `--hidden`
|
||||
- `-e`, `--extensions <.ext|.ext2>`
|
||||
- `--dry-run`
|
||||
- `--yes`
|
||||
|
||||
## Description
|
||||
Sequentially removes literal substrings from file and directory names. Every token is applied in the
|
||||
order provided, and the resulting name is used for subsequent removals before any filesystem rename
|
||||
occurs.
|
||||
|
||||
## Arguments & Flags
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `<pattern...>` | Yes (≥1) | Literal substrings to remove sequentially. Quotes required when tokens contain spaces. |
|
||||
|
||||
| Flag | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `--path` | string | `.` | Working directory for traversal (global flag). |
|
||||
| `-r`, `--recursive` | bool | `false` | Traverse subdirectories (global flag). |
|
||||
| `-d`, `--include-dirs` | bool | `false` | Include directory names in removal scope (global flag). |
|
||||
| `--hidden` | bool | `false` | Include hidden files/directories (global flag). |
|
||||
| `-e`, `--extensions` | string | (none) | Restrict removals to files matching `|`-delimited extensions (global flag). |
|
||||
| `--dry-run` | bool | `false` | Preview only; print proposed removals without applying (global flag). |
|
||||
| `--yes` | bool | `false` | Apply changes without interactive prompt (global flag). |
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | Meaning | Example Trigger |
|
||||
|------|---------|-----------------|
|
||||
| `0` | Success | Preview completed or apply executed without conflicts. |
|
||||
| `2` | Validation error | No patterns provided, empty token after trimming, unreadable directory. |
|
||||
| `3` | Conflict detected | Target filename already exists after removals. |
|
||||
|
||||
## Preview Output
|
||||
- Lists each impacted item with columns: `PATH`, `TOKENS REMOVED`, `NEW PATH`.
|
||||
- Summary line: `Total: <candidates> (changed: <count>, empties: <skipped>, conflicts: <count>)`.
|
||||
|
||||
## Apply Behavior
|
||||
- Re-validates preview results, then performs renames in sequence while tracking undo metadata.
|
||||
- Writes ledger entry containing ordered token list and per-token match counts.
|
||||
- Aborts without partial renames if conflicts arise between preview and apply.
|
||||
|
||||
## Validation Rules
|
||||
- Tokens are deduplicated case-sensitively but order of first occurrence preserved; duplicates logged
|
||||
as warnings.
|
||||
- Resulting names that collapse to empty strings are skipped with warnings.
|
||||
- Conflicts (targets already existing) abort the operation; users must resolve manually.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
renamer remove " copy" " draft"
|
||||
renamer remove foo foo- bar --path ./reports --recursive --dry-run
|
||||
renamer remove "Project X" " X" --extensions .txt|.md --yes
|
||||
```
|
||||
47
specs/003-add-remove-command/data-model.md
Normal file
47
specs/003-add-remove-command/data-model.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Data Model: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
## Entities
|
||||
|
||||
### RemoveRequest
|
||||
- **Description**: Captures inputs driving a remove operation.
|
||||
- **Fields**:
|
||||
- `workingDir` (string): Absolute path where traversal begins.
|
||||
- `tokens` ([]string): Ordered list of literal substrings to remove sequentially.
|
||||
- `includeDirectories` (bool): Whether directory names participate.
|
||||
- `recursive` (bool): Whether to traverse subdirectories.
|
||||
- `includeHidden` (bool): Include hidden files/directories when true.
|
||||
- `extensions` ([]string): Optional extension filters inherited from global scope flags.
|
||||
- `dryRun` (bool): Preview flag; true during preview, false for apply.
|
||||
- **Validations**:
|
||||
- `tokens` MUST contain at least one non-empty string after trimming.
|
||||
- `workingDir` MUST exist and be readable prior to traversal.
|
||||
- `tokens` are deduplicated case-sensitively but order of first occurrence preserved.
|
||||
|
||||
### RemoveSummary
|
||||
- **Description**: Aggregates preview/apply outcomes for reporting and ledger.
|
||||
- **Fields**:
|
||||
- `totalCandidates` (int): Count of files/directories evaluated.
|
||||
- `changedCount` (int): Count of items whose names change after removals.
|
||||
- `tokenMatches` (map[string]int): Number of occurrences removed per token (ordered in ledger metadata).
|
||||
- `conflicts` ([]ConflictDetail): Detected rename conflicts preventing apply.
|
||||
- `empties` ([]string): Relative paths where removal would lead to empty basename (skipped).
|
||||
|
||||
### ConflictDetail
|
||||
- **Description**: Captures rename conflicts detected during preview.
|
||||
- **Fields**:
|
||||
- `originalPath` (string)
|
||||
- `proposedPath` (string)
|
||||
- `reason` (string)
|
||||
|
||||
## Relationships
|
||||
- `RemoveRequest` feeds traversal utilities to produce candidate names.
|
||||
- `RemoveSummary` aggregates results from sequential removal engine and is persisted to ledger entries.
|
||||
- `ConflictDetail` entries inform preview output and determine which renames are skipped.
|
||||
|
||||
## State Transitions
|
||||
1. **Parse**: CLI arguments parsed into `RemoveRequest`; validations ensure tokens and scope are valid.
|
||||
2. **Preview**: Sequential removal engine produces proposed names, conflicts, and warnings recorded in
|
||||
`RemoveSummary`.
|
||||
3. **Apply**: Upon confirmation/`--yes`, renames execute (in dependency order), ledger entry written
|
||||
with ordered token metadata.
|
||||
4. **Undo**: Ledger reverse operation uses stored operations to restore original names.
|
||||
94
specs/003-add-remove-command/plan.md
Normal file
94
specs/003-add-remove-command/plan.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Implementation Plan: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
**Branch**: `003-add-remove-command` | **Date**: 2025-10-29 | **Spec**: [spec.md](./spec.md)
|
||||
**Input**: Feature specification from `/specs/003-add-remove-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
|
||||
|
||||
Introduce a `renamer remove` subcommand that deletes multiple literal substrings sequentially while
|
||||
respecting preview → confirm → ledger → undo guarantees. The command must evaluate all removals in
|
||||
memory before touching the filesystem to avoid excessive IO and ensure conflict detection happens on
|
||||
final names.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: Go 1.24
|
||||
**Primary Dependencies**: `spf13/cobra`, `spf13/pflag`
|
||||
**Storage**: Local filesystem only (ledger persisted as `.renamer`)
|
||||
**Testing**: Go `testing` package with contract, integration, and unit tests
|
||||
**Target Platform**: Cross-platform CLI (Linux, macOS, Windows)
|
||||
**Project Type**: Single CLI project
|
||||
**Performance Goals**: Preview + apply for 100 files completes within 2 minutes
|
||||
**Constraints**: Deterministic previews, reversible ledger entries, conflict/empty-name detection before apply
|
||||
**Scale/Scope**: Handles hundreds of files per invocation; token list expected to be small (≤20 literals)
|
||||
|
||||
## 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).
|
||||
- Undo strategy MUST describe how the `.renamer` ledger entry is written and reversed (Persistent Undo Ledger).
|
||||
- Planned remove rules MUST document their inputs, validations, and composing order (Composable Rule Engine).
|
||||
- Scope handling MUST cover files vs directories (`-d`), recursion (`-r`), and extension filtering via `-e` without escaping the requested path (Scope-Aware Traversal).
|
||||
- CLI UX plan MUST confirm Cobra usage, flag naming, help text, and automated tests for preview/undo flows (Ergonomic CLI Stewardship).
|
||||
|
||||
**Gate Alignment**:
|
||||
- Remove command will reuse preview/confirm pipeline; no rename occurs before preview approval.
|
||||
- Ledger entries will include ordered tokens removed per file to maintain undo guarantees.
|
||||
- Removal logic will be implemented as composable rule(s) similar to replace, enabling reuse and testing.
|
||||
- Command will consume shared scope flags (`--path`, `-r`, `-d`, `--hidden`, `-e`, `--dry-run`, `--yes`).
|
||||
- Cobra wiring + automated tests will cover help text, sequential behavior warnings, and undo parity.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/003-add-remove-command/
|
||||
├── plan.md
|
||||
├── research.md
|
||||
├── data-model.md
|
||||
├── quickstart.md
|
||||
├── contracts/
|
||||
└── tasks.md
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
cmd/
|
||||
├── root.go
|
||||
├── list.go
|
||||
├── replace.go
|
||||
├── remove.go # new CLI command for sequential removal
|
||||
└── undo.go
|
||||
|
||||
internal/
|
||||
├── listing/
|
||||
├── replace/
|
||||
├── remove/ # new package mirroring replace for request/parser/engine/summary
|
||||
├── output/
|
||||
├── traversal/
|
||||
└── history/
|
||||
|
||||
scripts/
|
||||
├── smoke-test-list.sh
|
||||
├── smoke-test-replace.sh
|
||||
└── smoke-test-remove.sh # new end-to-end smoke test
|
||||
|
||||
tests/
|
||||
├── contract/
|
||||
├── integration/
|
||||
├── unit/
|
||||
└── fixtures/
|
||||
```
|
||||
|
||||
**Structure Decision**: Single CLI repository with new remove-specific logic under `internal/remove/`
|
||||
and CLI wiring in `cmd/remove.go`. Tests follow the existing contract/integration/unit layout and a
|
||||
new smoke test script will live under `scripts/`.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
No constitution gate violations identified; no additional complexity justification required.
|
||||
57
specs/003-add-remove-command/quickstart.md
Normal file
57
specs/003-add-remove-command/quickstart.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Quickstart: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
## Goal
|
||||
Demonstrate how to delete multiple substrings sequentially from filenames while using the
|
||||
preview → apply → undo workflow safely.
|
||||
|
||||
## Prerequisites
|
||||
- Go toolchain (>= 1.24) installed for building the CLI locally.
|
||||
- Sample directory containing files with recurring tokens (e.g., `draft`, `copy`).
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Build the CLI**
|
||||
```bash
|
||||
go build -o renamer ./...
|
||||
```
|
||||
|
||||
2. **Inspect remove help**
|
||||
```bash
|
||||
./renamer remove --help
|
||||
```
|
||||
Pay attention to sequential behavior: tokens execute in the order provided.
|
||||
|
||||
3. **Run a preview with multiple tokens**
|
||||
```bash
|
||||
./renamer remove " copy" " draft" --path ./samples --dry-run
|
||||
```
|
||||
Confirm the output table shows each token removed in order and the summary reflects changed files.
|
||||
|
||||
4. **Apply removals after review**
|
||||
```bash
|
||||
./renamer remove " copy" " draft" --path ./samples --yes
|
||||
```
|
||||
Verify filenames no longer contain the tokens and a ledger entry is created.
|
||||
|
||||
5. **Undo if necessary**
|
||||
```bash
|
||||
./renamer undo --path ./samples
|
||||
```
|
||||
Ensure filenames return to their original state.
|
||||
|
||||
6. **Handle empty-result warnings**
|
||||
```bash
|
||||
./renamer remove "project" "project-" --path ./samples --dry-run
|
||||
```
|
||||
Expect the preview to warn and skip items that would collapse to empty names.
|
||||
|
||||
7. **Integrate into automation**
|
||||
```bash
|
||||
./renamer remove foo bar --dry-run && \
|
||||
./renamer remove foo bar --yes --path ./automation
|
||||
```
|
||||
Use non-zero exit codes to detect invalid input in scripts.
|
||||
|
||||
## Next Steps
|
||||
- Add contract tests covering sequential removals and empty-name warnings.
|
||||
- Extend documentation (CLI reference, changelog) with remove command examples.
|
||||
37
specs/003-add-remove-command/research.md
Normal file
37
specs/003-add-remove-command/research.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Phase 0 Research: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
## Decision: Sequential removal executed in-memory before filesystem writes
|
||||
- **Rationale**: Computing the full rename plan in memory guarantees deterministic previews,
|
||||
simplifies conflict detection, and avoids partial renames that could increase IO load or leave the
|
||||
filesystem inconsistent.
|
||||
- **Alternatives considered**:
|
||||
- *Apply-and-check per token*: rejected due to repeated filesystem mutations and difficulty keeping
|
||||
undo history coherent.
|
||||
- *Streaming rename per file*: rejected because conflicts can only be detected after all tokens
|
||||
apply.
|
||||
|
||||
## Decision: Dedicated `internal/remove` package mirroring replace architecture
|
||||
- **Rationale**: Keeps responsibilities separated (parser, engine, summary) and allows reuse of
|
||||
traversal/history helpers. Aligns with Composable Rule Engine principle.
|
||||
- **Alternatives considered**:
|
||||
- *Extending replace package*: rejected to avoid coupling distinct behaviors and tests.
|
||||
- *Embedding logic directly in command*: rejected for testability and maintainability reasons.
|
||||
|
||||
## Decision: Empty-result handling warns and skips rename
|
||||
- **Rationale**: Removing multiple tokens could produce empty basenames; skipping prevents creating
|
||||
invalid filenames while still informing the user.
|
||||
- **Alternatives considered**:
|
||||
- *Allow empty names*: rejected as unsafe and difficult to undo cleanly on certain filesystems.
|
||||
- *Hard fail entire batch*: rejected because unaffected files should still be processed.
|
||||
|
||||
## Decision: Ledger metadata records ordered tokens and counts
|
||||
- **Rationale**: Automation and undo workflows need insight into which tokens were removed and how
|
||||
often, mirroring replace’s metadata for consistency.
|
||||
- **Alternatives considered**:
|
||||
- *Only store operations*: insufficient for auditing complex removals.
|
||||
|
||||
## Decision: CLI help & quickstart emphasize ordering semantics
|
||||
- **Rationale**: Sequential behavior is the primary mental model difference from other commands; clear
|
||||
documentation reduces support load and user confusion.
|
||||
- **Alternatives considered**:
|
||||
- *Rely on examples alone*: risk of users assuming parallel removal and encountering surprises.
|
||||
140
specs/003-add-remove-command/spec.md
Normal file
140
specs/003-add-remove-command/spec.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Feature Specification: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
**Feature Branch**: `003-add-remove-command`
|
||||
**Created**: 2025-10-29
|
||||
**Status**: Draft
|
||||
**Input**: User description: "添加 移除(Remove)命令,用于删除指定字符、字符串,支持同时删除多个字符串,示例:renamer remove str1 str2 ....,注意:多个移除时后续参数的移除依赖于前一个移除后的结果,移除计算完成前不进行重命名,避免IO负载过高"
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Remove Unwanted Tokens in One Pass (Priority: P1)
|
||||
|
||||
As a CLI user tidying filenames, I want `renamer remove` to delete multiple substrings in order so I
|
||||
can normalize file names without writing custom scripts.
|
||||
|
||||
**Why this priority**: Delivers the core value—batch cleanup of recurring tokens across many files
|
||||
with predictable results.
|
||||
|
||||
**Independent Test**: Run `renamer remove " copy" " draft" --dry-run` in a sample directory,
|
||||
confirm preview shows the ordered removal effects, then apply with `--yes` and verify names update
|
||||
accordingly.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** files `report copy draft.txt` and `notes draft.txt`, **When** the user runs
|
||||
`renamer remove " copy" " draft"`, **Then** the preview shows both tokens removed sequentially
|
||||
and execution produces `report.txt` and `notes.txt`.
|
||||
2. **Given** patterns where later removals depend on earlier results (e.g., removing `foo` then `foo-`),
|
||||
**When** the command runs, **Then** each removal applies to the output of the previous step before
|
||||
computing rename conflicts.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Script-Friendly Removal Workflow (Priority: P2)
|
||||
|
||||
As an operator automating rename tasks, I want deterministic previews, exit codes, and ledger entries
|
||||
so scripts can run `renamer remove` safely without interactive prompts.
|
||||
|
||||
**Why this priority**: Ensures automation pipelines can rely on the same safety guarantees as manual
|
||||
runs.
|
||||
|
||||
**Independent Test**: In a CI script, call `renamer remove ... --dry-run`, assert exit code 0, then
|
||||
run with `--yes` and verify ledger entry plus `renamer undo` restores originals.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a non-interactive context, **When** the user passes `--yes` after a successful preview,
|
||||
**Then** the command exits 0 on success and writes a ledger entry capturing tokens removed per file.
|
||||
2. **Given** invalid input (e.g., fewer than two arguments), **When** the command executes, **Then** it
|
||||
exits with non-zero status and instructs the user on correct sequential argument usage.
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - Validate Sequential Removal Inputs (Priority: P3)
|
||||
|
||||
As a power user managing complex token lists, I want clear validation and guidance for spaces,
|
||||
duplicate tokens, and results that could produce empty filenames so I can adjust before applying.
|
||||
|
||||
**Why this priority**: Prevents surprise failures when tokens overlap or yield empty names.
|
||||
|
||||
**Independent Test**: Run `renamer remove "Project X" " Project" "X" --dry-run`, confirm preview
|
||||
shows the sequential impact and warns if names collapse; invalid quoting should produce actionable
|
||||
errors.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** duplicate tokens, **When** the command runs, **Then** duplicates are deduplicated with a
|
||||
warning and order preserved for remaining unique tokens.
|
||||
2. **Given** a removal sequence that would produce an empty basename, **When** the preview runs,
|
||||
**Then** the command warns and excludes the rename unless the user overrides in a future version.
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- Sequential removals should operate on the output of prior removals within the same filename.
|
||||
- Removing tokens may collapse names to empty strings or leave trailing separators; preview must flag
|
||||
these cases before apply.
|
||||
- Resulting names may collide; conflicts must be reported before confirmation.
|
||||
- Hidden files or directories may need inclusion depending on scope flags (`--hidden`).
|
||||
- No matches should result in a friendly "No entries matched" message and exit code 0 without ledger
|
||||
writes.
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: The CLI MUST expose `renamer remove <pattern1> [pattern2 ...]` where all tokens are
|
||||
literal substrings removed sequentially; final name computation MUST complete before any renames
|
||||
occur.
|
||||
- **FR-002**: Preview → confirm workflow MUST mirror existing commands, listing original and proposed
|
||||
names with highlighted removals.
|
||||
- **FR-003**: Executions MUST append detailed entries to `.renamer` including original names, tokens
|
||||
removed (with order), resulting names, and timestamps so undo remains possible.
|
||||
- **FR-004**: Users MUST be able to undo the most recent remove batch via existing undo mechanics
|
||||
without leaving orphaned files.
|
||||
- **FR-005**: Command MUST respect global scope flags (`--path`, `--recursive`, `--include-dirs`,
|
||||
`--hidden`, `--extensions`, `--dry-run`, `--yes`) identical to `list` / `replace` behavior.
|
||||
- **FR-006**: Preview MUST evaluate all removals first, calculate conflicts, and only then apply
|
||||
filesystem operations when confirmed, limiting IO load.
|
||||
- **FR-007**: Command MUST warn (and skip) renames that would result in empty basenames unless a
|
||||
future explicit override flag is provided.
|
||||
- **FR-008**: Invalid invocations (fewer than two arguments, empty tokens after trimming) MUST fail
|
||||
with exit code ≠0 and actionable usage guidance.
|
||||
- **FR-009**: Help output MUST document sequential behavior, whitespace quoting, and interaction with
|
||||
other scope flags.
|
||||
|
||||
### Key Entities
|
||||
|
||||
- **RemoveRequest**: Captures working directory, scope flags, ordered token list, and preview/apply
|
||||
options.
|
||||
- **RemoveSummary**: Aggregates per-token match counts, per-file outcomes, conflicts, and warnings for
|
||||
preview and ledger output.
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: Users complete a sequential removal across 100 files (preview + apply) in under 2
|
||||
minutes end-to-end.
|
||||
- **SC-002**: 95% of usability test participants correctly understand that removals execute in the
|
||||
provided order after reading `renamer remove --help`.
|
||||
- **SC-003**: Automated regression tests confirm remove + undo leave the filesystem unchanged in
|
||||
100% of scripted scenarios.
|
||||
- **SC-004**: Support requests related to manual substring cleanup drop by 35% within the first release
|
||||
cycle after launch.
|
||||
|
||||
## Assumptions
|
||||
|
||||
- Removals are literal substring matches; regex or wildcard support is out of scope for this release.
|
||||
- Default matching is case-sensitive; case-insensitive options can be considered later if needed.
|
||||
- Delete operations target filenames (and directories when `-d/--include-dirs` is set), not file
|
||||
contents.
|
||||
- Existing traversal, conflict detection, and ledger infrastructure can be extended for the remove
|
||||
command.
|
||||
|
||||
## Dependencies & Risks
|
||||
|
||||
- Requires new remove-specific packages analogous to replace to maintain modularity.
|
||||
- Help/quickstart documentation must be updated to explain sequential removal behavior.
|
||||
- Potential filename conflicts or empty results must be detected pre-apply to avoid data loss.
|
||||
168
specs/003-add-remove-command/tasks.md
Normal file
168
specs/003-add-remove-command/tasks.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Tasks: Remove Command with Sequential Multi-Pattern Support
|
||||
|
||||
**Input**: Design documents from `/specs/003-add-remove-command/`
|
||||
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
||||
|
||||
## Phase 1: Setup (Shared Infrastructure)
|
||||
|
||||
**Purpose**: Prepare shared fixtures and tooling used across all remove command user stories.
|
||||
|
||||
- [X] T001 Create remove command fixture directories (`basic/`, `conflicts/`, `empties/`) with placeholder files and README in `tests/fixtures/remove-samples/`.
|
||||
- [X] T002 [P] Author baseline smoke script showing preview → apply → undo flow for remove command in `scripts/smoke-test-remove.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Core remove command structures required before any user story implementation.
|
||||
|
||||
**⚠️ CRITICAL**: No user story work can begin until this phase is complete.
|
||||
|
||||
- [X] T003 [P] Define `RemoveRequest` struct plus validation and scope adaptation helpers in `internal/remove/request.go`.
|
||||
- [X] T004 [P] Implement argument parsing (trimming, minimum token count, parse result object) in `internal/remove/parser.go`.
|
||||
- [X] T005 [P] Create remove summary types and aggregation helpers for counts/conflicts in `internal/remove/summary.go`.
|
||||
- [X] T006 Build traversal adapter that reuses listing scope to enumerate candidates for removal in `internal/remove/traversal.go`.
|
||||
|
||||
**Checkpoint**: Foundation ready—user story implementation can now begin in parallel.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Remove Unwanted Tokens in One Pass (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Deliver sequential substring removal with preview and apply, covering the core filename cleanup workflow.
|
||||
|
||||
**Independent Test**: Run `renamer remove " copy" " draft" --dry-run` against `tests/fixtures/remove-samples/basic`, verify preview ordering, then apply with `--yes` and confirm filesystem changes.
|
||||
|
||||
### Tests for User Story 1 ⚠️
|
||||
|
||||
- [ ] T007 [P] [US1] Add unit tests covering sequential token application and unchanged cases in `tests/unit/remove_engine_test.go`.
|
||||
- [ ] T008 [P] [US1] Create contract test validating preview table output and dry-run messaging in `tests/contract/remove_command_preview_test.go`.
|
||||
- [ ] T009 [P] [US1] Write integration test exercising preview → apply flow with multiple files in `tests/integration/remove_flow_test.go`.
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [ ] T010 [US1] Implement sequential removal engine producing planned operations in `internal/remove/engine.go`.
|
||||
- [ ] T011 [US1] Build preview pipeline that aggregates summaries, detects conflicts, and streams output in `internal/remove/preview.go`.
|
||||
- [ ] T012 [US1] Implement apply pipeline executing planned operations without ledger writes in `internal/remove/apply.go`.
|
||||
- [ ] T013 [US1] Wire new Cobra command in `cmd/remove.go` (with registration in `cmd/root.go`) to drive preview/apply using shared scope flags.
|
||||
|
||||
**Checkpoint**: User Story 1 functional end-to-end with preview/apply validated by automated tests.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Script-Friendly Removal Workflow (Priority: P2)
|
||||
|
||||
**Goal**: Ensure automation can run `renamer remove` non-interactively with deterministic exit codes and ledger-backed undo.
|
||||
|
||||
**Independent Test**: Execute `renamer remove foo bar --dry-run` followed by `--yes` inside CI fixture, verify exit code 0 on success, ledger metadata persists tokens, and `renamer undo` restores originals.
|
||||
|
||||
### Tests for User Story 2 ⚠️
|
||||
|
||||
- [ ] T014 [P] [US2] Add contract test asserting ledger entries capture ordered tokens and match counts in `tests/contract/remove_command_ledger_test.go`.
|
||||
- [ ] T015 [P] [US2] Add integration test covering `--yes` automation path and subsequent undo in `tests/integration/remove_undo_test.go`.
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [ ] T016 [US2] Extend apply pipeline to append ledger entries with ordered tokens and match counts in `internal/remove/apply.go`.
|
||||
- [ ] T017 [US2] Update `cmd/remove.go` to support non-interactive `--yes` execution, emit automation-oriented messages, and propagate exit codes.
|
||||
|
||||
**Checkpoint**: User Story 2 complete—CLI safe for scripting with ledger + undo parity.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 - Validate Sequential Removal Inputs (Priority: P3)
|
||||
|
||||
**Goal**: Provide clear validation and warnings for duplicate tokens, empty results, and risky removals.
|
||||
|
||||
**Independent Test**: Run `renamer remove "Project X" " Project" "X" --dry-run` and confirm duplicate dedupe warnings plus empty-result skips appear in preview output.
|
||||
|
||||
### Tests for User Story 3 ⚠️
|
||||
|
||||
- [ ] T018 [P] [US3] Add parser validation tests for duplicate tokens and whitespace edge cases in `tests/unit/remove_parser_test.go`.
|
||||
- [ ] T019 [P] [US3] Add integration test verifying empty-basename warnings and skips in `tests/integration/remove_validation_test.go`.
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [ ] T020 [US3] Implement duplicate token deduplication with ordered warning collection in `internal/remove/parser.go`.
|
||||
- [ ] T021 [US3] Add empty-basename detection and warning tracking in `internal/remove/summary.go`.
|
||||
- [ ] T022 [US3] Surface duplicate and empty warnings in CLI output handling within `cmd/remove.go`.
|
||||
|
||||
**Checkpoint**: All user stories deliver value; validations prevent risky rename plans.
|
||||
|
||||
---
|
||||
|
||||
## Final Phase: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Documentation, tooling, and quality improvements spanning all user stories.
|
||||
|
||||
- [ ] T023 [P] Update remove command documentation and sequential behavior guidance in `docs/cli-flags.md`.
|
||||
- [ ] T024 Record release notes for remove command launch in `docs/CHANGELOG.md`.
|
||||
- [ ] T025 [P] Finalize `scripts/smoke-test-remove.sh` with assertions and integrate into CI instructions.
|
||||
- [ ] T026 Add remove command walkthrough to project onboarding materials in `AGENTS.md`.
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Setup (Phase 1)**: No dependencies—start immediately.
|
||||
- **Foundational (Phase 2)**: Depends on Setup completion—BLOCKS all user stories.
|
||||
- **User Stories (Phase 3–5)**: Each depends on Foundational phase; implement in priority order (P1 → P2 → P3) or in parallel once shared blockers clear.
|
||||
- **Polish (Final Phase)**: Depends on completion of targeted user stories.
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **US1 (P1)**: Requires Foundational tasks (T003–T006).
|
||||
- **US2 (P2)**: Requires US1 core command and apply pipeline (T010–T013).
|
||||
- **US3 (P3)**: Requires parser and summary scaffolding plus US1 preview pipeline (T004–T013).
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- Tests (if included) MUST be authored before implementation tasks.
|
||||
- Engine/traversal logic precedes CLI wiring for predictable integration.
|
||||
- Command wiring completes only after engine/preview/apply logic is ready.
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- Setup tasks (T001–T002) can run in parallel.
|
||||
- Foundational tasks marked [P] (T003–T005) may proceed concurrently after directory scaffolding.
|
||||
- US1 test tasks (T007–T009) can run in parallel once fixtures exist.
|
||||
- US2 and US3 test tasks (T014–T019) can execute concurrently after their respective foundations.
|
||||
- Polish tasks marked [P] (T023, T025) can occur alongside documentation updates.
|
||||
|
||||
---
|
||||
|
||||
## Parallel Example: User Story 1
|
||||
|
||||
```bash
|
||||
# Parallel test development for US1:
|
||||
# - T007: tests/unit/remove_engine_test.go
|
||||
# - T008: tests/contract/remove_command_preview_test.go
|
||||
# - T009: tests/integration/remove_flow_test.go
|
||||
#
|
||||
# Once tests are in place, run them together:
|
||||
go test ./tests/unit ./tests/contract ./tests/integration -run Remove
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
|
||||
1. Complete Phase 1 (Setup) and Phase 2 (Foundational).
|
||||
2. Finish Phase 3 (US1) delivering preview/apply with automated coverage.
|
||||
3. Validate with `go test ./...` and smoke script before moving on.
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. Deliver US1 (core removal) → release MVP.
|
||||
2. Add US2 (automation + ledger) → publish update.
|
||||
3. Enhance with US3 (advanced validation) → finalize release notes.
|
||||
|
||||
### Parallel Team Strategy
|
||||
|
||||
- After Phase 2, one developer tackles US1 implementation while another starts US2 tests.
|
||||
- US3 validation enhancements can begin once parser scaffolding lands, overlapping with documentation polish.
|
||||
- Conclude with Polish phase tasks to align docs, smoke tests, and onboarding materials.
|
||||
Reference in New Issue
Block a user