Add insert command

This commit is contained in:
Rogee
2025-10-30 15:15:16 +08:00
parent 6a353b5086
commit a0d7084c28
35 changed files with 2044 additions and 37 deletions

View File

@@ -0,0 +1,34 @@
# Specification Quality Checklist: Insert Command for Positional Text Injection
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2025-10-30
**Feature**: specs/001-add-insert-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,243 @@
openapi: 3.1.0
info:
title: Renamer Insert Command API
version: 0.1.0
description: >
Contract representation of the `renamer insert` command workflows (preview/apply/undo)
for automation harnesses and documentation parity.
servers:
- url: cli://renamer
description: Command-line invocation surface
paths:
/insert/preview:
post:
summary: Preview insert operations
description: Mirrors `renamer insert <position> <text> --dry-run`
operationId: previewInsert
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/InsertRequest'
responses:
'200':
description: Successful preview
content:
application/json:
schema:
$ref: '#/components/schemas/InsertPreview'
'400':
description: Validation error (invalid position, empty text, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/insert/apply:
post:
summary: Apply insert operations
description: Mirrors `renamer insert <position> <text> --yes`
operationId: applyInsert
requestBody:
required: true
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/InsertRequest'
- type: object
properties:
dryRun:
type: boolean
const: false
responses:
'200':
description: Apply succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/InsertApplyResult'
'409':
description: Conflict detected (duplicate targets, existing files)
content:
application/json:
schema:
$ref: '#/components/schemas/ConflictResponse'
'400':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/insert/undo:
post:
summary: Undo latest insert batch
description: Mirrors `renamer undo` when last ledger entry corresponds to insert command.
operationId: undoInsert
responses:
'200':
description: Undo succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/UndoResult'
'409':
description: Ledger inconsistent or no insert entry found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
InsertRequest:
type: object
required:
- workingDir
- positionToken
- insertText
properties:
workingDir:
type: string
positionToken:
type: string
description: '^', '$', positive integer, or negative integer.
insertText:
type: string
description: Unicode string to insert (must not contain path separators).
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
InsertPreview:
type: object
required:
- totalCandidates
- totalChanged
- noChange
- entries
properties:
totalCandidates:
type: integer
minimum: 0
totalChanged:
type: integer
minimum: 0
noChange:
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'
InsertApplyResult:
type: object
required:
- totalApplied
- noChange
- ledgerEntryId
properties:
totalApplied:
type: integer
minimum: 0
noChange:
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
- invalid_position
- existing_file
- existing_directory
PreviewEntry:
type: object
required:
- originalPath
- proposedPath
- status
properties:
originalPath:
type: string
proposedPath:
type: string
status:
type: string
enum:
- changed
- no_change
- skipped
insertedText:
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 Insert Command
## Entity: InsertRequest
- **Fields**
- `WorkingDir string` — Absolute path derived from CLI `--path` or current directory.
- `PositionToken string` — Raw user input (`^`, `$`, positive int, negative int) describing insertion point.
- `InsertText string` — Unicode string to insert.
- `IncludeDirs bool` — Mirrors `--include-dirs` scope flag.
- `Recursive bool` — Mirrors `--recursive`.
- `IncludeHidden bool` — True only when `--hidden` supplied.
- `ExtensionFilter []string` — Normalized 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**
- Reject empty `InsertText`, path separators, or control characters.
- Ensure `PositionToken` parses to a valid rune index relative to the stem (`^` = 0, `$` = len, positive 1-based, negative = offset from end).
- Confirm resulting filename is non-empty and does not change extension semantics.
- **Relationships**
- Consumed by insert engine to plan operations.
- Serialized into ledger metadata with `InsertSummary`.
## Entity: InsertSummary
- **Fields**
- `TotalCandidates int` — Items inspected after scope filtering.
- `TotalChanged int` — Entries that will change after insertion.
- `NoChange int` — Entries already containing target string at position (if applicable).
- `Conflicts []Conflict` — Target collisions or invalid positions.
- `Warnings []string` — Validation notices (duplicates, trimmed tokens, skipped hidden items).
- `Entries []PreviewEntry` — Ordered original/proposed mappings with status.
- `LedgerMetadata map[string]any` — Snapshot persisted with ledger entry (position, text, scope flags).
- **Validation Rules**
- Conflicts must be empty before apply.
- `TotalChanged + NoChange` equals count of entries with status `changed` or `no_change`.
- Entries sorted deterministically by original path.
- **Relationships**
- Emitted to preview renderer and ledger writer.
- Input for undo verification.
## Entity: Conflict
- **Fields**
- `OriginalPath string`
- `ProposedPath string`
- `Reason string` — (`duplicate_target`, `invalid_position`, `existing_file`, etc.)
- **Validation Rules**
- `ProposedPath` unique among planned operations.
- Reason restricted to known enum values for messaging.
- **Relationships**
- Reported in preview output and used to block apply.
## Entity: PreviewEntry
- **Fields**
- `OriginalPath string`
- `ProposedPath string`
- `Status string``changed`, `no_change`, `skipped`.
- `InsertedText string` — Text segment inserted (for auditing).
- **Validation Rules**
- `ProposedPath` equals `OriginalPath` when `Status == "no_change"`.
- `InsertedText` empty only for `no_change` or `skipped`.
- **Relationships**
- Displayed in preview output.
- Persisted with ledger metadata for undo playback.

View File

@@ -0,0 +1,105 @@
# Implementation Plan: Insert Command for Positional Text Injection
**Branch**: `005-add-insert-command` | **Date**: 2025-10-30 | **Spec**: `specs/005-add-insert-command/spec.md`
**Input**: Feature specification from `/specs/005-add-insert-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 insert` subcommand that inserts a specified string into filenames at designated positions (start, end, absolute, relative) with Unicode-aware behavior, deterministic previews, ledger-backed undo, and automation-friendly outputs.
## Technical Context
<!--
ACTION REQUIRED: Replace the content in this section with the technical details
for the project. The structure here is presented in advisory capacity to guide
the iteration process.
-->
**Language/Version**: Go 1.24
**Primary Dependencies**: `spf13/cobra`, `spf13/pflag`, internal traversal/history/output packages
**Storage**: Local filesystem + `.renamer` ledger files
**Testing**: `go test ./...`, contract + integration suites under `tests/`, new smoke script
**Target Platform**: Cross-platform CLI (Linux, macOS, Windows shells)
**Project Type**: Single CLI project (`cmd/`, `internal/`, `tests/`, `scripts/`)
**Performance Goals**: 500-file insert (preview+apply) completes in <2 minutes end-to-end
**Constraints**: Unicode-aware insertion points, preview-first safety, ledger reversibility
**Scale/Scope**: Operates on thousands of filesystem 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). ✅ Extend insert preview to render original → proposed names with highlighted insertion segments before any apply.
- Undo strategy MUST describe how the `.renamer` ledger entry is written and reversed (Persistent Undo Ledger). ✅ Reuse ledger append with metadata (position token, inserted string) and ensure `undo` replays operations safely.
- Planned rename rules MUST document their inputs, validations, and composing order (Composable Rule Engine). ✅ Define an insert rule consuming position tokens, performing Unicode-aware slicing, and integrating with existing traversal pipeline.
- Scope handling MUST cover files vs directories (`-d`), recursion (`-r`), and extension filtering via `-e` without escaping the requested path (Scope-Aware Traversal). ✅ Leverage shared listing/traversal flags so insert respects scope filters and hidden/default exclusions.
- 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 consistent flags, help examples, contract/integration tests, and smoke coverage.
*Post-Design Verification (2025-10-30): Research and design artifacts document preview behavior, ledger metadata, Unicode-aware positions, and CLI UX updates — no gate violations detected.*
## Project Structure
### Documentation (this feature)
```text
specs/[###-feature]/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── data-model.md # Phase 1 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
```
### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```text
cmd/
├── root.go
├── list.go
├── replace.go
├── remove.go
├── extension.go
└── undo.go
internal/
├── filters/
├── history/
├── listing/
├── output/
├── remove/
├── replace/
├── extension/
└── traversal/
tests/
├── contract/
├── integration/
├── fixtures/
└── unit/
scripts/
├── smoke-test-list.sh
├── smoke-test-replace.sh
├── smoke-test-remove.sh
└── smoke-test-extension.sh
```
**Structure Decision**: Extend the single CLI project by adding new `cmd/insert.go`, `internal/insert/` package, contract/integration coverage under existing `tests/` hierarchy, and an insert smoke script alongside other command scripts.
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |

View File

@@ -0,0 +1,28 @@
# Quickstart Insert Command
1. **Preview an insertion at the start of filenames.**
```bash
renamer insert ^ "[2025] " --dry-run
```
- Shows the prepended tag without applying changes.
- Useful for tagging archival folders.
2. **Insert text near the end while preserving extensions.**
```bash
renamer insert -1 "_FINAL" --path ./reports --dry-run
```
- `-1` places the string before the last character of the stem.
- Combine with `--extensions` to limit to specific file types.
3. **Commit changes once preview looks correct.**
```bash
renamer insert 3 "_QA" --yes --path ./builds
```
- `--yes` auto-confirms using the last preview.
- Ledger entry records the position token and inserted text.
4. **Undo the most recent insert batch if needed.**
```bash
renamer undo --path ./builds
```
- Restores original names using ledger metadata.

View File

@@ -0,0 +1,17 @@
# Phase 0 Research Insert Command
## Decision: Reuse Traversal + Preview Pipeline for Insert Rule
- **Rationale**: Existing replace/remove/extension commands share a scope walker and preview formatter that already respect `--path`, `-r`, `--hidden`, and ledger logging. Extending this infrastructure minimizes duplication and guarantees constitutional compliance for preview-first safety.
- **Alternatives considered**: Building a standalone walker for insert was rejected because it risks divergence in conflict handling and ledger metadata. Hooking insert into `replace` internals was rejected to keep rule responsibilities separated.
## Decision: Interpret Positions Using Unicode Code Points on Filename Stems
- **Rationale**: Gos rune indexing treats each Unicode code point as one element, aligning with user expectations for multilingual filenames. Operating on the stem (excluding extension) keeps behavior consistent with common batch-renaming tools.
- **Alternatives considered**: Byte-based offsets were rejected because multi-byte characters would break user expectations. Treating the full filename including extension was rejected to avoid forcing users to re-add extensions manually.
## Decision: Ledger Metadata Includes Position Token and Inserted Text
- **Rationale**: Storing the position directive (`^`, `$`, positive, negative) and inserted string enables precise undo, auditing, and potential future analytics. This mirrors how replace/remove log the rule context.
- **Alternatives considered**: Logging only before/after paths was rejected because it obscures the applied rule and complicates debugging automated runs.
## Decision: Block Apply on Duplicate Targets or Invalid Positions
- **Rationale**: Preventing collisions and out-of-range indices prior to file mutations preserves data integrity and meets preview-first guarantees. Existing conflict detection helpers can be adapted for insert.
- **Alternatives considered**: Allowing apply with overwrites was rejected due to high data-loss risk. Auto-truncating positions was rejected because silent fallback leads to inconsistent results across files.

View File

@@ -0,0 +1,101 @@
# Feature Specification: Insert Command for Positional Text Injection
**Feature Branch**: `005-add-insert-command`
**Created**: 2025-10-30
**Status**: Draft
**Input**: User description: "实现插入Insert字符支持在文件名指定位置插入指定字符串数据示例 renamer insert <position> <string>, position:可以包含 ^:开头、$:结尾、 正数:字符位置、负数:倒数字符位置。!!重要:需要考虑中文字符"
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Insert Text at Target Position (Priority: P1)
As a power user organizing media files, I want to insert a label into filenames at a specific character position so that I can batch-tag assets without manually editing each name.
**Why this priority**: Provides the core value proposition of the insert command—precise, repeatable filename updates that accelerate organization tasks.
**Independent Test**: In a sample directory with mixed filenames, run `renamer insert 3 _tag --dry-run` and verify the preview shows the marker inserted at the third character (Unicode-aware). Re-run with `--yes` to confirm filesystem changes and ledger entry.
**Acceptance Scenarios**:
1. **Given** files named `项目A报告.docx` and `项目B报告.docx`, **When** the user runs `renamer insert ^ 2025- --dry-run`, **Then** the preview lists `2025-项目A报告.docx` and `2025-项目B报告.docx`.
2. **Given** files named `holiday.jpg` and `trip.jpg`, **When** the user runs `renamer insert -1 X --yes`, **Then** the apply step inserts `X` before the last character of each base name while preserving extensions.
---
### User Story 2 - Automation-Friendly Batch Inserts (Priority: P2)
As an operator running renamer in CI, I need deterministic exit codes, ledger metadata, and undo support when inserting text so scripted jobs remain auditable and reversible.
**Why this priority**: Ensures production and automation workflows can rely on the new command without risking data loss.
**Independent Test**: Execute `renamer insert $ _ARCHIVE --yes --path ./fixtures`, verify exit code `0`, inspect the latest `.renamer` entry for recorded positions/string, then run `renamer undo` to restore originals.
**Acceptance Scenarios**:
1. **Given** a non-interactive run with `--yes`, **When** insertion completes without conflicts, **Then** exit code is `0` and the ledger stores the original names, position rule, inserted text, and timestamps.
2. **Given** a ledger entry produced by `renamer insert`, **When** `renamer undo` executes, **Then** all affected files revert to their exact previous names even across locales.
---
### User Story 3 - Validate Positions and Multilingual Inputs (Priority: P3)
As a user preparing filenames with multilingual characters, I want validation and preview warnings for invalid positions, overlapping results, or unsupported encodings so I can adjust commands before committing changes.
**Why this priority**: Protects against data corruption, especially with Unicode characters where byte counts differ from visible characters.
**Independent Test**: Run `renamer insert 50 _X --dry-run` on files shorter than 50 code points and confirm the command exits with a non-zero status explaining the out-of-range index; validate that Chinese filenames are handled correctly in previews.
**Acceptance Scenarios**:
1. **Given** an index larger than the filename length, **When** the command runs, **Then** it fails with a descriptive error and no filesystem changes occur.
2. **Given** an insertion that would create duplicate names, **When** preview executes, **Then** conflicts are surfaced and apply is blocked until resolved.
---
### Edge Cases
- What happens when the requested position is outside the filename length (positive or negative)?
- How are filenames handled when inserting before/after Unicode characters or surrogate pairs?
- How are directories or hidden files treated when `--include-dirs` or `--hidden` is omitted or provided?
- What feedback is provided when insertion would produce duplicate targets or empty names?
- How does the command behave when the inserted string is empty, whitespace-only, or contains path separators?
- What occurs when multiple files differ only by case and the insert results in conflicting targets on case-insensitive filesystems?
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: CLI MUST provide a dedicated `insert` subcommand accepting a positional argument (`^`, `$`, positive integer, or negative integer) and the string to insert.
- **FR-002**: Insert positions MUST be interpreted using Unicode code points on the filename stem (excluding extension) so multi-byte characters count as a single position.
- **FR-003**: The command MUST support scope flags (`--path`, `--recursive`, `--include-dirs`, `--hidden`, `--extensions`, `--dry-run`, `--yes`) consistent with existing commands.
- **FR-004**: Preview MUST display original and proposed names, highlighting inserted segments, and block apply when conflicts or invalid positions are detected.
- **FR-005**: Apply MUST update filesystem entries atomically per batch, record operations in the `.renamer` ledger with inserted string, position rule, affected files, and timestamps, and support undo.
- **FR-006**: Validation MUST reject positions outside the allowable range, empty insertion strings (unless explicitly allowed), and inputs containing path separators or control characters.
- **FR-007**: Help output MUST describe position semantics (`^`, `$`, positive, negative), Unicode handling, and examples for both files and directories.
- **FR-008**: Automation runs with `--yes` MUST emit deterministic exit codes (`0` success, non-zero on validation/conflicts) and human-readable messages that can be parsed for errors.
### Key Entities
- **InsertRequest**: Working directory, position token, insertion string, scope flags, dry-run/apply mode.
- **InsertSummary**: Counts of processed items, per-position match details, conflicts, warnings, and preview entries with status (`changed`, `no_change`, `skipped`).
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: Users insert text into 500 filenames (preview + apply) in under 2 minutes end-to-end.
- **SC-002**: 95% of beta users correctly apply a positional insert after reading `renamer insert --help` without additional guidance.
- **SC-003**: Automated regression tests confirm insert + undo cycles leave the filesystem unchanged in 100% of scripted scenarios.
- **SC-004**: Support tickets related to manual filename labeling drop by 30% within the first release cycle post-launch.
## Assumptions
- Positions operate on the filename stem (path excluded, extension preserved); inserting at `$` occurs immediately before the extension dot when present.
- Empty insertion strings are treated as invalid to avoid silent no-ops; users must provide at least one visible character.
- Unicode normalization is assumed to be NFC; filenames are treated as sequences of Unicode code points using the runtimes native string handling.
## Dependencies & Risks
- Requires reuse and possible extension of existing traversal, preview, and ledger infrastructure to accommodate positional operations.
- Accurate Unicode handling depends on the runtimes Unicode utilities; additional testing may be necessary for combining marks and surrogate pairs.
- Insertion near filesystem path separators must be restricted to avoid creating invalid paths or escape sequences.

View File

@@ -0,0 +1,158 @@
# Tasks: Insert Command for Positional Text Injection
**Input**: Design documents from `/specs/005-add-insert-command/`
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/
**Tests**: Contract and integration tests included per spec emphasis on preview determinism, ledger integrity, and Unicode handling.
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Establish initial command scaffolding and directories.
- [X] T001 Create insert package scaffolding `internal/insert/doc.go`
- [X] T002 Add placeholder Cobra command entry point `cmd/insert.go`
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Core parsing, summary structures, and helpers needed by all stories.
- [X] T003 Define `InsertRequest` builder and execution mode helpers in `internal/insert/request.go`
- [X] T004 Implement `InsertSummary`, preview entries, and conflict types in `internal/insert/summary.go`
- [X] T005 Build Unicode-aware position parsing and normalization utilities in `internal/insert/positions.go`
**Checkpoint**: Foundation ready — user story implementation can now begin.
---
## Phase 3: User Story 1 Insert Text at Target Position (Priority: P1) 🎯 MVP
**Goal**: Provide preview + apply flow that inserts text at specified positions with Unicode handling.
**Independent Test**: `renamer insert 3 _tag --dry-run` confirms preview insertion per code point ordering; `--yes` applies and ledger logs metadata.
### Tests
- [X] T006 [P] [US1] Add contract preview/apply coverage in `tests/contract/insert_command_test.go`
- [X] T007 [P] [US1] Add integration flow test for positional insert in `tests/integration/insert_flow_test.go`
### Implementation
- [X] T008 [US1] Implement planning engine to compute proposed names in `internal/insert/engine.go`
- [X] T009 [US1] Render preview output with highlighted segments in `internal/insert/preview.go`
- [X] T010 [US1] Apply filesystem changes with ledger logging in `internal/insert/apply.go`
- [X] T011 [US1] Wire Cobra command to parse args, perform preview/apply in `cmd/insert.go`
**Checkpoint**: User Story 1 functionality testable end-to-end.
---
## Phase 4: User Story 2 Automation-Friendly Batch Inserts (Priority: P2)
**Goal**: Ensure ledger metadata, undo, and exit codes support automation.
**Independent Test**: `renamer insert $ _ARCHIVE --yes --path ./fixtures` exits `0` with ledger metadata; `renamer undo` restores filenames.
### Tests
- [ ] T012 [P] [US2] Extend contract tests for ledger metadata & exit codes in `tests/contract/insert_ledger_test.go`
- [ ] T013 [P] [US2] Add automation/undo integration scenario in `tests/integration/insert_undo_test.go`
### Implementation
- [ ] T014 [US2] Persist position token and inserted text in ledger metadata via `internal/insert/apply.go`
- [ ] T015 [US2] Enhance undo CLI feedback for insert batches in `cmd/undo.go`
- [ ] T016 [US2] Ensure zero-match runs exit `0` with notice in `cmd/insert.go`
**Checkpoint**: User Stories 1 & 2 independently verifiable.
---
## Phase 5: User Story 3 Validate Positions and Multilingual Inputs (Priority: P3)
**Goal**: Robust validation, conflict detection, and messaging for out-of-range or conflicting inserts.
**Independent Test**: Invalid positions produce descriptive errors; duplicate targets block apply; Chinese filenames preview correctly.
### Tests
- [X] T017 [P] [US3] Add validation/conflict contract coverage in `tests/contract/insert_validation_test.go`
- [X] T018 [P] [US3] Add conflict-blocking integration scenario in `tests/integration/insert_validation_test.go`
### Implementation
- [X] T019 [US3] Implement parsing + error messaging for position tokens in `internal/insert/parser.go`
- [X] T020 [US3] Detect conflicting targets and report warnings in `internal/insert/conflicts.go`
- [X] T021 [US3] Surface validation failures and conflict gating in `cmd/insert.go`
**Checkpoint**: All user stories function with robust validation.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Documentation, tooling, and quality improvements.
- [X] T022 Update CLI flags documentation for insert command in `docs/cli-flags.md`
- [X] T023 Add insert smoke test script `scripts/smoke-test-insert.sh`
- [X] T024 Run gofmt and `go test ./...` from repo root `./`
---
## Dependencies & Execution Order
### Phase Dependencies
1. Phase 1 (Setup) → groundwork for new command/package.
2. Phase 2 (Foundational) → required before user story work.
3. Phase 3 (US1) → delivers MVP after foundational tasks.
4. Phase 4 (US2) → builds on US1 for automation support.
5. Phase 5 (US3) → extends validation/conflict handling.
6. Phase 6 (Polish) → final documentation and quality checks.
### User Story Dependencies
- US1 depends on foundational tasks only.
- US2 depends on US1 implementation (ledger/apply logic).
- US3 depends on US1 preview/apply and US2 ledger updates.
### Task Dependencies (selected)
- T008 requires T003T005.
- T009, T010 depend on T008.
- T011 depends on T008T010.
- T014 depends on T010.
- T015 depends on T014.
- T019 depends on T003, T005.
- T020 depends on T008, T009.
- T021 depends on T019T020.
---
## Parallel Execution Examples
- Within US1, tasks T006 and T007 can run in parallel once T011 is in progress.
- Within US2, tests T012/T013 may execute while T014T016 are implemented.
- Within US3, contract vs integration tests (T017/T018) can proceed concurrently after T021 adjustments.
---
## Implementation Strategy
### MVP (US1)
1. Complete Phases 12 foundation.
2. Deliver Phase 3 (US1) to enable core insert functionality.
3. Validate via contract/integration tests (T006/T007) and manual dry-run/apply checks.
### Incremental Delivery
- Phase 4 adds automation/undo guarantees after MVP.
- Phase 5 hardens validation and conflict management.
- Phase 6 completes documentation, smoke coverage, and regression checks.
### Parallel Approach
- One developer handles foundational + US1 engine.
- Another focuses on test coverage and CLI wiring after foundations.
- Additional developer can own US2 automation tasks while US1 finalizes, then US3 validation enhancements.