diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 58e23ce6..4d3aea3b 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -126,6 +126,7 @@ Input → VCS Detection → Version Parsing → Transformation → Format Output - **Environment variables**: `ZERV_TEST_NATIVE_GIT`, `ZERV_TEST_DOCKER` - **Git operations**: Always use `get_git_impl()` - **Docker tests**: Always use `should_run_docker_tests()` gating +- **CRITICAL**: For Git-related tests, **ALWAYS use `ZERV_TEST_NATIVE_GIT=false ZERV_TEST_DOCKER=true`** - **Integration tests**: Prefer `TestCommand::run_with_stdin()` (90% of cases) **For detailed testing patterns:** diff --git a/.claude/plan/32-zerv-flow-implementation-plan.md b/.claude/plan/32-zerv-flow-implementation-plan.md index 3a45234a..296a57d5 100644 --- a/.claude/plan/32-zerv-flow-implementation-plan.md +++ b/.claude/plan/32-zerv-flow-implementation-plan.md @@ -103,18 +103,18 @@ This section demonstrates how Zerv Flow works across different branching strateg **Scenario Overview**: - Development starts from `v1.0.0` on main -- Three feature branches created in parallel: `feature-1`, `feature-2`, and later `feature-3` +- Two feature branches created in parallel: `feature-1` and `feature-2` - `feature-1` gets completed and released first (`v1.0.1`) - `feature-2` syncs with main to get `feature-1` changes, then continues development -- `feature-3` branches from `feature-2` to implement a sub-feature -- `feature-3` merges back to `feature-2`, which then releases as `v1.1.0` +- `feature-3` branches from `feature-2` to implement a sub-feature (nested feature branch) +- `feature-3` merges back to `feature-2`, which then completes development and releases as `v1.1.0` **Key Zerv Flow behaviors demonstrated**: - **Uncommitted changes**: Shows dirty state with `.dev.timestamp` suffix -- **Parallel development**: Different branches get unique hash-based IDs (`12345`, `54321`, `98765`) +- **Parallel development**: Different branches get unique hash-based IDs (`68031`, `42954`, `14698`) - **Version progression**: Base version updates when syncing with main (`1.0.1` → `1.0.2`) -- **Post-release distance resets**: Counters reset to `.post.1` after syncing with new base version +- **Post-release distance continuity**: Distance counters continue accumulating across branches and merges - **Nested feature branches**: `feature-3` branching from `feature-2` with independent versioning - **Merge handling**: Clean version progression through complex merge scenarios - **Alpha pre-releases**: All development branches use `alpha` pre-release identifiers @@ -126,36 +126,56 @@ config: theme: 'base' --- gitGraph + %% Step 1: Initial commit on main with v1.0.0 tag commit id: "1.0.0" + %% Step 2: Create parallel feature branches feature-1 and feature-2 from main branch feature-1 order: 2 branch feature-2 order: 3 + %% Step 3: feature-2: Start development with dirty state checkout feature-2 - commit type:REVERSE id: "1.0.1-alpha.12345.post.0.dev.1729924622" tag: "uncommitted" - commit id: "1.0.1-alpha.12345.post.1" + commit type:REVERSE id: "1.0.1-alpha.68031.post.0.dev.{timestamp}" tag: "uncommitted" + %% Step 4: feature-2: Create first commit + commit id: "1.0.1-alpha.68031.post.1" + + %% Step 5: feature-1: Create commits (parallel development) checkout feature-1 - commit id: "1.0.1-alpha.54321.post.1" - commit id: "1.0.1-alpha.54321.post.2" + commit id: "1.0.1-alpha.42954.post.1" + commit id: "1.0.1-alpha.42954.post.2" + %% Step 6: feature-1: Merge to main and release v1.0.1 checkout main merge feature-1 id: "1.0.1" tag: "feature-1 released" + %% Step 7: feature-2: Sync with main to get feature-1 changes checkout feature-2 - merge main id: "1.0.2-alpha.12345.post.1" - commit id: "1.0.2-alpha.12345.post.2" + merge main id: "1.0.2-alpha.68031.post.2" + + %% Step 8: feature-2: Create additional commit + commit id: "1.0.2-alpha.68031.post.3" + %% Step 9: feature-3: Branch from feature-2 for sub-feature development branch feature-3 order: 4 checkout feature-3 - commit id: "1.0.2-alpha.98765.post.3" - commit type:REVERSE id: "1.0.2-alpha.98765.post.3.dev.1729924622" tag: "uncommitted" - commit id: "1.0.2-alpha.98765.post.4" + commit id: "1.0.2-alpha.14698.post.4" + + %% Step 10: feature-3: Continue development with dirty state + commit type:REVERSE id: "1.0.2-alpha.14698.post.4.dev.{timestamp}" tag: "uncommitted" + %% Step 11: feature-3: Continue development with commits + commit id: "1.0.2-alpha.14698.post.5" + commit id: "1.0.2-alpha.14698.post.6" + + %% Step 12: feature-2: Merge feature-3 back to continue development checkout feature-2 - merge feature-3 id: "1.0.2-alpha.12345.post.3" tag: "feature-3 merged" + merge feature-3 id: "1.0.2-alpha.68031.post.6" tag: "feature-3 merged" + + %% Step 13: feature-2: Final development before release + commit id: "1.0.2-alpha.68031.post.7" - commit id: "1.0.2-alpha.12345.post.4" + %% Step 14: Final release: feature-2 merges to main and releases v1.1.0 checkout main merge feature-2 id: "1.1.0" tag: "feature-2 released" ``` @@ -179,7 +199,8 @@ gitGraph - **RC pre-releases**: Release branches use `rc` identifier for release candidates - **Clean releases**: Main branch maintains clean versions without pre-release suffixes - **Hotfix emergency flow**: Critical fixes from main with proper version propagation -- **Post-release resolution**: Correct post counting based on pre-release type changes +- **Release branch post mode**: `release/*` branches use post distance from release tag (commit distance) +- **Trunk-based post mode**: Other branches use post distance from branch point (for parallel development) - **Base version propagation**: Version bumps when syncing branches with newer main releases ```mermaid @@ -189,43 +210,57 @@ config: theme: 'base' --- gitGraph + %% Step 1: Initial state: main and develop branches commit id: "1.0.0" + %% Step 2: Create develop branch with initial development commit branch develop order: 3 checkout develop commit id: "1.0.1-beta.1.post.1" + %% Step 3: Feature development from develop branch (trunk-based post mode) branch feature/auth order: 4 checkout feature/auth - commit id: "1.0.1-alpha.12345.post.1" - commit id: "1.0.1-alpha.12345.post.2" + commit id: "1.0.1-alpha.92409.post.2" + commit id: "1.0.1-alpha.92409.post.3" checkout develop - merge feature/auth id: "1.0.1-beta.1.post.2" tag: "feature merged" + %% Step 4: Merge feature/auth back to develop + merge feature/auth id: "1.0.1-beta.1.post.3" tag: "feature merged" + %% Step 5: Hotfix emergency flow from main checkout main branch hotfix/critical order: 1 checkout hotfix/critical - commit id: "1.0.1-alpha.54321.post.1" + commit id: "1.0.1-alpha.11477.post.1" checkout main - merge hotfix/critical id: "1.0.1" tag: "tagged" + %% Step 6: Merge hotfix to main and release v1.0.1 + merge hotfix/critical id: "1.0.1" tag: "hotfix released" + %% Step 7: Sync develop with main changes and continue development checkout develop - merge main id: "1.0.2-beta.1.post.3" tag: "update main" - commit id: "1.0.2-beta.1.post.4" + merge main id: "1.0.2-beta.1.post.4" tag: "sync main" + + %% Step 8: Continue development on develop branch + commit id: "1.0.2-beta.1.post.5" + %% Step 9: Release branch preparation (release/* uses commit distance from tag) branch release/1 order: 2 checkout release/1 commit id: "1.0.2-rc.1.post.1" tag: "tagged" commit id: "1.0.2-rc.1.post.2" tag: "tagged" - commit id: "1.0.2-rc.1.post.2.dev.1729924622" + commit type:REVERSE id: "1.0.2-rc.1.post.2.dev.{timestamp1}" tag: "uncommit" + commit id: "1.0.2-rc.1.post.2.dev.{timestamp2}" tag: "untagged" + commit id: "1.0.2-rc.1.post.3" tag: "tagged" checkout main - merge release/1 id: "1.1.0" tag: "tagged" + %% Step 10: Final release: merge release/1 to main + merge release/1 id: "1.1.0" tag: "release 1.1.0" + %% Step 11: Sync develop with release and prepare for next cycle checkout develop - merge main id: "1.1.1-beta.1.post.1" tag: "update main" + merge main id: "1.1.1-beta.1.post.1" tag: "sync release" ``` ## Scope and Limitations diff --git a/.claude/plan/33-zerv-flow-cli-command-design.md b/.claude/plan/33-zerv-flow-cli-command-design.md index d6b85d84..4696301a 100644 --- a/.claude/plan/33-zerv-flow-cli-command-design.md +++ b/.claude/plan/33-zerv-flow-cli-command-design.md @@ -39,17 +39,62 @@ zerv flow [OPTIONS] --bumped-branch Override branch name for pre-release resolution (same as zerv version) --bumped-branch-hash-length Branch hash length for pre-release numbers [default: 5] [range: 4..16] --post-mode Post calculation mode [default: tag] [possible values: tag, commit] - --build-context Include build context (+branch.commit) in output [default: true] - --no-build-context Exclude build context from output - --dev-ts Include dev timestamp for dirty working directory [default: auto-detect] - --no-dev-ts Exclude dev timestamp from output - --with-pre-release Include pre-release/post-release but no build context - --base-only Base version only (major.minor.patch) + --schema Schema variant for output components [default: standard] [possible values: standard, standard-no-context, standard-context, standard-base, standard-base-prerelease, standard-base-prerelease-post, standard-base-prerelease-post-dev] -v, --verbose Show verbose output including version resolution details -h, --help Print help -V, --version Print version ``` +### Schema System + +**zerv flow uses the flexible schema system from zerv version but restricted to standard schema family only.** + +#### Available Standard Schema Variants + +- **`standard`** (default) - Smart context: includes context only for dirty/distance states, excludes for clean tagged +- **`standard-no-context`** - Never includes build context (branch.commit info) +- **`standard-context`** - Always includes build context +- **`standard-base`** - Base version only (e.g., `1.2.3`) +- **`standard-base-prerelease`** - Base + prerelease (e.g., `1.2.3-alpha.1`) +- **`standard-base-prerelease-post`** - Base + prerelease + post (e.g., `1.2.3-alpha.1.post.2`) +- **`standard-base-prerelease-post-dev`** - Base + prerelease + post + dev (e.g., `1.2.3-alpha.1.post.2.dev.123`) + +#### Schema Behavior Examples + +**Smart Context (`standard` - default):** + +- Clean tagged commit: `1.0.1-rc.1.post.1` +- Dirty working directory: `1.0.1-rc.1.post.1.dev.1729924622+feature.auth.1.a1b2c3d` +- Distance from tag: `1.0.1-rc.1.post.2+feature.auth.2.c2d3e4f` + +**No Context (`standard-no-context`):** + +- Any state: `1.0.1-rc.1.post.1` (never includes +branch.commit) + +**Always Context (`standard-context`):** + +- Any state: `1.0.1-rc.1.post.1+feature.auth.1.a1b2c3d` (always includes context) + +**Base Components:** + +- `standard-base`: `1.2.3` +- `standard-base-prerelease`: `1.2.3-alpha.1` +- `standard-base-prerelease-post`: `1.2.3-alpha.1.post.2` +- `standard-base-prerelease-post-dev`: `1.2.3-alpha.1.post.2.dev.123` + +#### Schema Validation + +**Only standard schema family supported in zerv flow:** + +- ✅ **Valid**: `standard`, `standard-no-context`, `standard-context`, `standard-base`, `standard-base-prerelease`, `standard-base-prerelease-post`, `standard-base-prerelease-post-dev` +- ❌ **Invalid**: Any `calver*` schema variants will produce error +- ❌ **Invalid**: Any deprecated tier-based schemas will produce error + +**Error handling:** + +- Non-standard schemas will result in: `Error: zerv flow only supports standard schema variants, got: 'calver'` +- Invalid schema names will result in: `Error: Unknown schema variant: 'invalid-schema'` + ## Pre-release Resolution Logic ### Default Behavior (no flags) @@ -162,17 +207,21 @@ zerv flow --branch-rules ### Manual Override -**Mutually exclusive with `--pre-release-from-branch`:** +**Schema can be combined with manual pre-release overrides:** ```bash -# Force specific pre-release type and number -zerv flow --pre-release-label beta --pre-release-num 1 +# Force specific pre-release type and number with context +zerv flow --pre-release-label beta --pre-release-num 1 --schema standard-context + +# Force rc for release-like branches, no context +zerv flow --pre-release-label rc --pre-release-num 2 --schema standard-base-prerelease-post -# Force rc for release-like branches -zerv flow --pre-release-label rc --pre-release-num 2 +# Force alpha for feature branches with full context +zerv flow --pre-release-label alpha --schema standard-base-prerelease-post-dev-context -# Force alpha for feature branches (uses hash by default) -zerv flow --pre-release-label alpha +# Manual overrides with different schema levels +zerv flow --pre-release-label beta --schema standard-base-prerelease +zerv flow --pre-release-label rc --schema standard-base ``` ### Branch Override @@ -180,25 +229,32 @@ zerv flow --pre-release-label alpha **Test different branch scenarios without switching branches:** ```bash -zerv flow --bumped-branch develop --pre-release-from-branch -zerv flow --bumped-branch release/1 --pre-release-from-branch +# Test develop branch with different schemas +zerv flow --bumped-branch develop --schema standard +zerv flow --bumped-branch develop --schema standard-no-context + +# Test release branch with specific schema +zerv flow --bumped-branch release/1 --schema standard-base-prerelease-post-context + +# Test feature branch scenarios +zerv flow --bumped-branch feature/auth --schema standard-base-prerelease-post-dev ``` ## Output Modes -### Full Output (default) +### Full Output (default - `standard` schema) ``` 1.0.1-alpha.12345.post.2.dev.1729924622+feature.auth.2.a1b2c3d ``` -### Pre-release Output (`--with-pre-release`) +### Pre-release Output (`--schema standard-base-prerelease-post`) ``` 1.0.1-alpha.12345.post.2 ``` -### Base-Only Output (`--base-only`) +### Base-Only Output (`--schema standard-base`) ``` 1.0.1 @@ -235,36 +291,42 @@ zerv flow --bumped-branch release/1 --pre-release-from-branch ### Basic Usage ```bash -# Generate flow version with automatic pre-release +# Generate flow version with smart context (default schema) zerv flow -# Enable branch pattern detection (GitFlow) -zerv flow --pre-release-from-branch - # Force specific pre-release type zerv flow --pre-release-label beta # Include pre-release/post-release but no build context -zerv flow --with-pre-release +zerv flow --schema standard-base-prerelease-post # Base version only -zerv flow --base-only +zerv flow --schema standard-base + +# Never include build context +zerv flow --schema standard-no-context + +# Always include build context +zerv flow --schema standard-context ``` ### Advanced Usage ```bash -# Complete control over pre-release -zerv flow --bumped-branch release/1 --pre-release-from-branch +# Complete control over pre-release with schema +zerv flow --bumped-branch release/1 --schema standard-base-prerelease-post-context -# Custom template output -zerv flow --output-template "v{{version}}-{{pre_release}}" +# Custom template output with specific schema +zerv flow --schema standard-base --output-template "v{{version}}-{{pre_release}}" # Different repository directory -zerv flow --directory ../other-repo +zerv flow --directory ../other-repo --schema standard # Verbose output -zerv flow --verbose +zerv flow --verbose --schema standard-base-prerelease-post-dev + +# Error case - this will fail with calver schema +zerv flow --schema calver # Error: zerv flow only supports standard schema variants ``` ## Future Configuration @@ -291,11 +353,11 @@ zerv flow --config .zerv.ron ## Key Design Principles -1. **Mirror zerv version**: Same output/input options structure -2. **Intelligent defaults**: Smart branch-based pre-release detection -3. **Flexible overrides**: Manual control when needed -4. **Honest versioning**: Never hides Git state, always accurate -5. **Clean alternatives**: `--with-pre-release` and `--base-only` for simplified output +1. **Mirror zerv version**: Same output/input options structure with shared schema system +2. **Intelligent defaults**: Smart branch-based pre-release detection with smart context schema +3. **Flexible overrides**: Manual control when needed, including schema selection +4. **Honest versioning**: Never hides Git state, always accurate (unless explicitly requested via schema) +5. **Schema-based flexibility**: Single `--schema` argument replaces multiple context/control flags --- diff --git a/.claude/plan/39-implement-zerv-flow-schema-system.md b/.claude/plan/39-implement-zerv-flow-schema-system.md new file mode 100644 index 00000000..f1584022 --- /dev/null +++ b/.claude/plan/39-implement-zerv-flow-schema-system.md @@ -0,0 +1,389 @@ +# Implement Zerv Flow Schema System + +**Status**: Planned +**Priority**: High +**Context**: Refactor zerv flow CLI arguments to use flexible schema system, consolidating multiple context/control flags into a single `--schema` argument that leverages the existing schema system from zerv version. + +## Current State Analysis + +### Existing Flow Arguments (src/cli/flow/args/main.rs) + +```rust +// Currently implemented context flags to be replaced +--dev-ts / --no-dev-ts // Controls dev timestamp inclusion ✅ IMPLEMENTED + +// Context flags from design doc that were never implemented +--build-context / --no-build-context // Controls build context inclusion ❌ NOT IMPLEMENTED +--with-pre-release // Include prerelease/post only ❌ NOT IMPLEMENTED +--base-only // Base version only ❌ NOT IMPLEMENTED + +// Context flags to be replaced (that are actually implemented) +--no-pre-release // Disable pre-release entirely ✅ IMPLEMENTED + +// Existing arguments to keep +--pre-release-label