Conversation
Establish the four foundational v1 decisions in docs/architecture.md, create the full module layout with stub files, and bootstrap the binary+library crate with all dependencies and CI workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement full CLI surface: copy (default), list, info, validate subcommands with global options (--source, --dest, -C, -q, -v) and copy-specific options (--dry-run, --overwrite). All commands return placeholder "not implemented" errors. Add 8 CLI integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement RepoRelPath with path normalization (accepts absolute/relative, rejects root-escape and repo-root-as-file). Add all domain types: RepoContext, ValidationReport, CopyPlan, PlannedEntry, CopyOp, InfoReport, GitIgnoreStatus, WorktreeincludeStatus, and supporting enums. 13 path normalization unit tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement GitBackend trait with GitCli concrete type. Methods: show_toplevel, list_worktrees, tracked_paths, check_ignore, list_worktreeinclude_candidates, read_bool_config. All Git output parsed from NUL-delimited formats. 8 parser unit tests for worktree list and check-ignore output parsing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement resolve_context() that turns CLI inputs into a validated RepoContext. Handles auto-detection of linked vs main worktree, requires --dest for copy from main worktree, rejects source==dest and destinations outside the worktree family. 5 unit tests with mock GitBackend. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Discover and validate all .gitignore, .worktreeinclude, and .git/info/exclude files using GitignoreBuilder. Reports errors for in-repo files and warnings for global excludes. Detects symlinked .worktreeinclude files. 5 validation unit tests with real git repos. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement per-directory .worktreeinclude evaluation with last-match-wins semantics. Collects applicable files from repo root to queried path's parent, builds matchers per directory using GitignoreBuilder. Returns Included/ExcludedByNegation/NoMatch with file, line, and pattern. 13 unit tests covering globs, negation, nesting, anchored patterns, directory-only patterns, **, and case-insensitive matching. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire list command: resolve context, validate, enumerate candidates via git ls-files --exclude-per-directory=.worktreeinclude, filter through git check-ignore, sort and print. Wire validate command with error/ warning output. Verbose list mode includes worktreeinclude explanations. 7 integration tests with real git repos covering root patterns, nested overrides, tracked file exclusion, ** patterns, and sorted output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Info shows per-path status: tracked/ignored/worktreeinclude status, source existence/kind, copy eligibility, and destination state when a dest worktree is known. Uses both Git backend (ls-files, check-ignore) and worktreeinclude explanation engine. 5 integration tests covering tracked files, ignored+included, missing files, and multi-path queries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement planner with destination classification (Missing, UpToDate, UntrackedConflict, TrackedConflict, TypeConflict, UnsafePath), sorted deterministic entries, and dry-run rendering. Implement executor with atomic temp-file-then-rename writes, symlink safety checks, permission preservation, and continue-on-error semantics. Wire copy command with full pipeline: context resolution, validation, candidate enumeration, ignore filtering, planning, and execution. FileSystem trait enables mock testing. 6 planner unit tests, 7 copy integration tests including worktree auto-detection, dry-run, overwrite, and conflict handling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 6 deterministic differential tests and 1 property-based test comparing wiff list output against Git oracle (ls-files + check-ignore). Tests cover: simple patterns, nested overrides, **, negation chains, tracked file exclusion, and .git/info/exclude. Address Codex review findings: - Fix inverted ValidationSeverity doc comments - Use trim_end_matches for show_toplevel instead of trim() - Remove trim() on NUL-delimited path entries - Enforce source=main worktree and dest=linked worktree for copy - Make RepoRelPath::from_normalized pub(crate) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add comprehensive crate-level docs in lib.rs explaining architecture, key decisions, and module organization. Rewrite README.md with usage examples, .worktreeinclude format guide, eligibility rules, safety guarantees, and command reference. Expand architecture.md with command pipeline and testing strategy sections. Add doc-build job to CI matrix. Add release workflow stub triggered by version tags. Fix rustdoc broken intra-doc link warning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The info command was using ad hoc destination checks (existence, file type, content equality) instead of the planner's classify_destination logic. This meant it never detected tracked conflicts, untracked conflicts, or unsafe paths — reporting generic "exists (differs)" instead. Now info reuses planner::classify_destination to emit proper DestinationState labels (tracked-conflict, untracked-conflict, type-conflict, unsafe-path, up-to-date, missing) aligned with the planner's taxonomy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address Codex review feedback: classify_destination assumes source is a regular file (matching planner preconditions). When source is missing or non-regular, the read-based comparison would incorrectly fall through to UntrackedConflict. Now info only invokes full classification when source exists and is a regular file; otherwise it reports basic existence. Added edge-case test for missing source with existing destination. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion as complete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nd predicted actions The list -v output previously only showed a debug-formatted WorktreeincludeStatus. Now it includes: source file size, gitignore source/line/pattern, worktreeinclude source/line/pattern, and (when --dest is provided) the predicted copy action via classify_destination — matching the spec contract from InitialSpecDocument.txt lines 355-362. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Match planner preconditions: symlinks and non-regular-file sources are skipped by the planner, so verbose list should report "skip (unsupported source type)" instead of running classify_destination on them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…plete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nd negation caveat Two bugs fixed: 1. Path duplication for nested .worktreeinclude files: evaluate_file used file_dir.join(rel_path) which doubled directory segments (e.g. config/config/foo). Now uses repo_root.join(rel_path) for correct absolute path construction. 2. Git negation caveat not enforced: per-line matchers couldn't cross-reference patterns, so `dir/` + `!dir/keep` incorrectly deselected dir/keep. Now builds a single combined matcher per file and explicitly checks parent directories when a whitelist (negation) match occurs — if a parent directory is selected, the negation cannot override it (matching Git's documented caveat). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
validate.rs was directly shelling out to `git config core.excludesFile`, violating the architectural boundary that all Git process invocations should go through git.rs. This adds a `read_config` method to `GitBackend` and rewrites `find_global_excludes` to use it, restoring testability with mock backends. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add four additional tests to strengthen validation of the nested path and negation caveat fixes: - nested anchored pattern does NOT match outside its directory scope - deeply nested anchored pattern (3+ levels) - negation caveat in nested .worktreeinclude files - negation without directory pattern still deselects (no false caveat) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The within-file negation caveat was already enforced (a `dir/` pattern in the same file blocks `!dir/keep`), but the cross-file case was not: if root `.worktreeinclude` selected a directory, a deeper file's negation could still deselect files inside it. Refactors evaluate_file into build_file_match_context + evaluate_against_context so matchers are retained for a post-loop cross_file_ancestor_check. When the final result is ExcludedByNegation, all accumulated matchers are checked for ancestor directory selections — matching Git's documented behavior that negation cannot override a parent directory selection regardless of which file the patterns come from. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-key-cases as complete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The fix was already applied in commit 384f1bc which moved the global excludes git config lookup behind the GitBackend trait. Verified that no direct Git process invocations remain outside git.rs in production code, and all existing tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The info command was skipping the validation phase that copy and list both run, allowing it to report results even when .gitignore or .worktreeinclude files contain errors. Now info mirrors the same validate-then-proceed pipeline as the other commands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Assert that validation blocks before any info output is produced (stdout should not contain "path:" on validation failure) - Remove no-op warning test that didn't exercise real warning behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The `-z` flag causes git to NUL-terminate each attribute field (replacing newlines), with a double-NUL separating records. The old parser split on NUL and then iterated `.lines()` within each chunk, which meant attributes like `bare` in their own NUL-delimited field were never associated with the correct worktree record. Replace with a stateful parser that processes NUL-delimited fields sequentially: `worktree <path>` starts a new record, subsequent fields are attributes of the current record, and an empty field (double-NUL) finalizes it. Update all test data to use the real -z byte format. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…sing Add edge case tests for locked/prunable attributes, paths with spaces, and missing trailing double-NUL to strengthen parser coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
walkdir does not follow symlinks by default, so symlink entries have is_symlink()=true and is_file()=false. The symlink check was nested inside the is_file() guard and was therefore unreachable for actual symlinks. Restructure discover_and_validate to check for symlinked .worktreeinclude entries before the is_file() gate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…re-not-rejected-by-validation Add integration test that exercises `wiff validate` against a repo with a symlinked .worktreeinclude, verifying the CLI reports the error and exits with a failure code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lidation as complete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add integration tests for tracked destination conflicts in copy command: - copy_skips_tracked_destination_conflict: verifies tracked dest files are skipped - copy_skips_tracked_destination_even_with_overwrite: verifies --overwrite cannot override the tracked-conflict protection Add differential explanation-parity tests comparing per-path explanation tuples (source file, line, pattern) from `wiff info` against `git check-ignore -v -n`, covering: simple patterns, globs, multi-line rules, negation chains, doublestar patterns, directory-slash patterns, and .git/info/exclude sources. These fill gaps identified in ImplementationPlan.txt step 12 (tracked destination conflicts) and step 13 (per-path explanation parity). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…mplete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validation previously only reported parse/read failures. Per the spec, it should also warn about suspicious-but-legal patterns. This adds two lint-style heuristics: - Shadowed negation: a negation like `!dir/file` after `dir/` was excluded is ineffective because git won't descend into excluded directories. - Duplicate pattern: the same pattern text appearing more than once in the same file. Both are reported as ValidationSeverity::Warning (non-fatal). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…pattern-warnings as complete Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
plx
commented
Apr 13, 2026
Owner
Author
plx
left a comment
There was a problem hiding this comment.
AGENT: this is a very good first draft. I've left some comments.
The big one is that I forgot to ask to setup a justfile to use for all project commands; for reference see the one in my other project: https://github.com/plx/ferric-rules .
Aside from that there's a few questions and a proposed refactoring—otherwise looks pretty good.
plx
added a commit
that referenced
this pull request
Apr 29, 2026
The architecture doc and module-level docs were written before the gix migration (PR #3) and the worktreeinclude-modes feature (PR #5). This re-checks them against the current code surface: - Decision #1: "Git CLI is authoritative" reframed as the GitBackend trait with two implementations (GitGix default, GitCli via WAFT_GIT_BACKEND=cli) backed by parity tests. - Decision #2: per-directory semantics are now one of three pluggable engines (claude-2026-04 default, git, wt-0.39); the per-directory discussion lives in its own section. - Repo layout adds config.rs, policy_filter.rs, worktreeinclude_engine.rs, the new test files, and the planning docs. - Command pipeline updated to 9 stages: policy resolution, select_candidates dispatch, post-selection policy filter. - README eligibility rule covers when_missing=all-ignored and the exclusion sets; the nested .worktreeinclude paragraph leads with the default (root-only) behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
plx
added a commit
that referenced
this pull request
Apr 30, 2026
* Document subcommands module and update architecture layout. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Refresh docs for gix backend and worktreeinclude modes. The architecture doc and module-level docs were written before the gix migration (PR #3) and the worktreeinclude-modes feature (PR #5). This re-checks them against the current code surface: - Decision #1: "Git CLI is authoritative" reframed as the GitBackend trait with two implementations (GitGix default, GitCli via WAFT_GIT_BACKEND=cli) backed by parity tests. - Decision #2: per-directory semantics are now one of three pluggable engines (claude-2026-04 default, git, wt-0.39); the per-directory discussion lives in its own section. - Repo layout adds config.rs, policy_filter.rs, worktreeinclude_engine.rs, the new test files, and the planning docs. - Command pipeline updated to 9 stages: policy resolution, select_candidates dispatch, post-selection policy filter. - README eligibility rule covers when_missing=all-ignored and the exclusion sets; the nested .worktreeinclude paragraph leads with the default (root-only) behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Opening for human and agent review.