fix: Graceful Default-Init Skip in Non-Fab-Managed Repos#29
Conversation
Treats fab sync exit code 3 (ExitNotManaged) as a no-op when the init script is the built-in default, instead of a hard init failure. An explicit WORKTREE_INIT_SCRIPT still hard-fails on any non-zero exit.
There was a problem hiding this comment.
Pull request overview
This PR updates wt’s default worktree init behavior so that when the built-in default init script (fab sync) is run in a non-fab-managed repository and exits with fab-kit’s ExitNotManaged = 3, wt treats it as a graceful “does not apply” no-op (warning + exit 0) rather than an init failure (exit 7 + banner/prompt). It also threads “default vs explicit” provenance (isDefault) so only the built-in default gets this carve-out; explicitly configured init scripts still hard-fail on any non-zero exit.
Changes:
InitScriptPath()now returns(script, isDefault)so callers can distinguish the built-in default from an explicitWORKTREE_INIT_SCRIPToverride (even if the override equals"fab sync").- Added a shared run-time classifier (
DefaultNotApplicable) and canonical warning renderer (RenderDefaultSkipWarning) and applied them consistently in both init run sites (wt createandwt init). - Added unit + integration tests (via stubbed
fab) and updated specs/memory docs to document the new “default-not-applicable” skip semantics.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/internal/worktree/init.go | Adds exit-code classifier + shared skip-warning renderer for the default “fab sync” non-managed case. |
| src/internal/worktree/init_test.go | Unit tests for the classifier and warning renderer. |
| src/internal/worktree/crud.go | Threads isDefault into init runner and applies the skip classification in wt create’s init path. |
| src/internal/worktree/context.go | Changes InitScriptPath() to return both script and provenance (isDefault). |
| src/internal/worktree/context_test.go | Updates/adds provenance tests for InitScriptPath() (including explicit "fab sync"). |
| src/cmd/wt/create.go | Passes (script, isDefault) through both init call sites. |
| src/cmd/wt/init.go | Applies the same skip classification in wt init, preserving TTY reclaim ordering. |
| src/cmd/wt/integration_test.go | Integration coverage using a stub fab to validate exit-3 skip vs exit-1 hard-fail and provenance gating. |
| docs/specs/init-protocol.md | Documents provenance reporting + the new run-time skip case and exit-3 carve-out. |
| docs/specs/cli-surface.md | Updates CLI exit-code semantics to reflect ExitInitFailed and the new non-failure skip outcomes. |
| docs/memory/wt-cli/init-failure-contract.md | Records the new default-not-applicable carve-out and shared-helper behavior. |
| docs/memory/wt-cli/create-output-phases.md | Notes the carve-out’s effect on wt init/wt create output/exit behavior. |
| fab/changes/260705-irnt-graceful-default-init-skip/intake.md | Captures requirements and design rationale for the change. |
| fab/changes/260705-irnt-graceful-default-init-skip/plan.md | Implementation plan and acceptance checklist for the change. |
| fab/changes/260705-irnt-graceful-default-init-skip/.status.yaml | Change metadata/status tracking. |
| fab/changes/260705-irnt-graceful-default-init-skip/.history.jsonl | Change execution history log. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // - On the default-not-applicable skip (isDefault AND exit 3, per | ||
| // DefaultNotApplicable), prints the skip warning to stderr and returns nil. | ||
| // - Returns the exec error verbatim on any other init-script non-zero exit so | ||
| // callers can extract *exec.ExitError via errors.As. |
There was a problem hiding this comment.
Fixed — doc comment now says the exec error is wrapped via %w (not returned verbatim), while keeping the errors.As extraction guarantee. (6294663)
Meta
irntexcludes
fab/,docs/· generated by fab-kit v2.13.4Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
Summary
wt's default init script (fab sync) previously treated any non-fab-managed repo as a hard init failure (exit 7, kept-worktree banner, open-anyway prompt), even though the user never opted into that default. This change treats fab-kit'sExitNotManaged = 3exit code as a graceful no-op when the init script is the built-in default, while an explicitly configuredWORKTREE_INIT_SCRIPTstill hard-fails on any non-zero exit.Changes
InitScriptPath()now signals provenance (isDefault) alongside the script string, so downstream logic can distinguish the built-in default from an explicit overridefab syncexits non-zero, a default script + exit code 3 is treated as "does not apply" (stderr warning, exit 0, no banner, no prompt); all other cases keep today's hard-failure behaviorisDefaultthroughRunWorktreeSetup/RunWorktreeSetupWithObserver(crud.go) andwt init(cmd/wt/init.go), plus bothwt createcall sites (cmd/wt/create.go)InitScriptPathprovenance, and end-to-endwt create/wt initbehavior via a stubbedfabbinarydocs/specs/init-protocol.mddocumenting the new skip case and provenance-based lookup contract