Path Discrepancies Are Identity Problems, Not Formatting Problems
Jul 04, 2026
When an operator types a repository path and the system disagrees about spelling, the visible bug looks like a casing or formatting problem. It usually is not. The durable fix is to reconcile Git's registered worktree identity against the filesystem object identity at the shared authority boundary — before confirmation, kickoff, or any scaffold side effect.
The problem
The symptom was a path mismatch: the operator supplied one spelling, the tool recorded another, and downstream workers rejected the resulting execution context as self-contradictory.
The first instinct is string normalization — lowercasing paths, case-insensitive comparison, or trimming whitespace. That treats the bug as formatting. In this case, the real failure was deeper: a mismatch between filesystem-resolved path text and Git's registered worktree identity. One path could be declared canonical while Git's spelling was incorrectly recorded as a secondary worktree, producing parallel truths that downstream systems correctly refused to accept.
The item initially looked like a narrow interactive-entry fix. A baseline audit showed that patching only the interactive facade would leave direct kickoff and start-item paths inconsistent. The correct solution had to sit at the shared resolver — the single authority boundary every entry path converges on.
What actually happened
The correct identity mechanism was filesystem object identity using device and inode values, not lowercasing paths or performing case-insensitive string comparison. That made the solution structural rather than platform-specific string handling.
Hidden complexity came from Git worktree states the original implementation never defined policy for:
- selected bare repository
- stale or prunable records
- unstatable registered paths
- malformed or empty porcelain output
- zero matching worktrees
- multiple matching worktrees
A specification stage added real value by forcing explicit policy for each of those cases rather than allowing implementation-specific guesses. An early spec audit correctly found contradictions around bare and prunable worktrees, which were resolved before build.
The implementation was structural and complete within scope:
- reconciliation moved into the shared resolver
- canonical Git spelling propagates through confirmation, kickoff, item state, item placement, and worker context
- secondaries are partitioned using the same identity relation
- unsupported or ambiguous states fail closed before scaffold
- no separate facade-specific identity logic was introduced
Verification exposed that implementation correctness alone was insufficient. The first evidence pass did not prove all entry paths, refusal classes, successful scaffold cases, and end-to-end equality invariants. Test hardening closed those gaps. Final verification covered real Git worktrees, linked worktrees, aliases, symlinks, paths with spaces, prunable records, bare records, and all typed refusal classes.
Manual acceptance still mattered despite extensive automated coverage. It proved the operator-facing flow converted one path spelling to Git's canonical spelling before continuing — the exact failure shape that triggered the item.
Residual risks are narrow: unusual worktree paths containing embedded newlines remain outside handled porcelain assumptions; object identity based on device and inode remains platform and filesystem dependent, though it is more correct than string normalization; interactive repository resolution now incurs a bounded Git subprocess call.
The lesson
A visible path discrepancy may indicate an identity-authority problem, not a formatting problem. Fix the authority boundary first.
When repository, workspace, or worktree paths disagree:
- Identify the canonical authority boundary before selecting files to change. If the proposed fix sits in a facade when a shared resolver exists, the facade patch will leave parallel paths inconsistent.
- Treat path issues as identity problems until proven otherwise. Git registration plus filesystem object identity is the comparison relation — not path spelling.
- Canonicalize before side effects. Identity reconciliation must happen before interactive confirmation and before any scaffold operation.
- Use one identity relation everywhere. The same relation that selects the authoritative worktree must exclude it from secondaries. Direct kickoff, start-item, and interactive entry must all converge on the same resolver.
- Define policy for every Git record class before build: live worktree, linked worktree, bare repository, prunable worktree, unstatable record, malformed output, zero match, ambiguous match. Unsupported or ambiguous states should fail closed.
- Require one equality invariant across all path-bearing surfaces rather than separate propagation assertions.
The broader principle
Facade-level fixes for authority problems create shadow paths — locally plausible changes that leave the system internally inconsistent. The factory pattern that works here applies broadly: when a symptom appears at one entry point, ask whether a shared authority boundary already exists. If it does, the fix belongs there.
Verification must map every acceptance criterion to a named observation at the correct system boundary. Passing helper tests is not proof of facade coverage, subprocess behavior, scaffold boundaries, or end-to-end path equality. For identity-sensitive changes, include both helper-level tests and real boundary tests through each public entry path, plus one operator-run smoke using the original failure shape.
Scope discipline matters. The final change correctly did not expand into general path normalization, target-repository repair, recursive discovery, or unrelated prompt or authentication changes.
How to apply it
For similar repository-path or worktree-identity items:
- Start with a baseline audit that asks: "Is the proposed fix being placed in a facade when a shared authority boundary exists?"
- Require a specification when the bug exposes undefined refusal or lifecycle policy, even when the code change appears small.
- Document the authoritative identity source, comparison relation, unsupported-state policy, ambiguity policy, and side-effect boundary before implementation.
- Prove canonical identity invariants across all entry paths and scaffold boundaries — not just value propagation through helpers.
- Keep manual acceptance mandatory for operator-visible CLI changes, even when automated coverage is extensive. Include the exact working directory and invocation surface in acceptance instructions, not only the nominal repository root.
When path spelling looks wrong, stop normalizing strings. Find where the system decides what repository identity means — and reconcile there, once, before anything irreversible happens.