Skip to content

fix(cli): fail closed when uninstall targets a missing directory - #430

Merged
barbatdev merged 1 commit into
mainfrom
fix/358-uninstall-missing-root
Nov 12, 2026
Merged

barbatdev merged 1 commit into
mainfrom
fix/358-uninstall-missing-root

Conversation

@barbatdev

Copy link
Copy Markdown
Contributor

Pull Request

Linked Issue

Fixes #358

PR Type

  • type:feature Feature
  • type:bug Bug fix
  • type:docs Documentation
  • type:refactor Refactoring
  • type:chore Maintenance
  • type:breaking-change Breaking change

Summary

uninstall --target-dir against a directory that does not exist reported not_installed with exit 0, while the same command against an existing empty directory exits 3. #342 requires both to fail closed. A missing directory now returns the same refusal as an existing directory with no Cortex ownership records.

Changes

  • internal/cli/doctor.go: the missing-root branch of runDirectoryUninstall returns exitConflict (3) instead of exitOK.
  • internal/cli/directory_lifecycle_test.go: tests for a missing root (new behavior) and an existing empty directory (existing behavior pinned).
  • docs/operating.md: documents exit 3 for a missing or never-installed --target-dir and exit 0 for the grouped uninstall.

Focused Tests

Claim Test command Observed result Limit State Observed by
A missing target directory fails closed go test ./internal/cli -count=1 -run TestUninstallDirectoryTarget before the fix exit = 0, want 3 Through runWithDependencies, not the shell binary Verified Agent that made the change
Same, after the fix Same command ok; stdout runtime=directory uninstall=not_installed remove=0 absent=0 conflict=0, exit 3, empty stderr, target still absent Same Verified Agent that made the change and parent re-run
An existing empty directory behaves as before TestUninstallDirectoryTargetFailsClosedWhenNotInstalled Passes before and after; directory stays empty Verified Agent that made the change
Grouped uninstall with missing roots is unchanged Existing internal/cli/uninstall_test.go Still exit 0 Verified Agent that made the change
Full suite go vet ./...; go test ./... -count=1; python3 -m unittest discover -s tests Clean; all packages ok; OK Verified Agent that made the change

Side effects: runDirectoryUninstall has one caller (uninstall --target-dir). Its shared helpers (uninstallRootExists, writeUninstallResult) are unchanged, so grouped uninstall, update and doctor keep their behavior.

Not tested: the real cortex binary from a shell.

Failed or not done: none.

Warnings: scripts that call uninstall --target-dir on a missing path now get exit 3 instead of 0. This is the behavior #358 requires. The refusal reuses the empty-directory output, which has no separate reason field.

Runtime Harness

N/A: CLI exit-code change covered by CLI tests; no runtime projection change.

Rollback

Revert the single commit.

Chain Dependencies / Out of Scope

Checklist

  • Linked issue is open and status:approved.
  • Exactly one matching type:* label is applied.
  • Focused tests and runtime harness evidence are recorded.
  • Rollback and out-of-scope boundaries are documented.

@barbatdev barbatdev added the type:bug Bug fix label Nov 12, 2026
@barbatdev

Copy link
Copy Markdown
Contributor Author

Fleet review (glm)

Lens: requirements + adversarial. The fix satisfies the #358 acceptance criterion quoted from #342 ("Running update/uninstall against a directory with no prior Cortex ownership fails closed with an explicit diagnostic"): a missing --target-dir now returns exitConflict (3) with uninstall=not_installed on stdout and empty stderr, identical to the already-accepted empty-directory behavior, and the missing path is not created on disk. Both cases are pinned by new tests (TestUninstallDirectoryTargetFailsClosedWhenRootMissing and ...WhenNotInstalled), grouped uninstall is confirmed unchanged via the existing uninstall_test.go, the shared helpers are untouched, and docs/operating.md documents the exit-code split. The change is minimal and consistent; the absence of a distinct reason token for a missing directory is documented as out of scope and the exit code is the discriminator, matching the previously approved behavior.

No findings.

Verdict: ready to merge

@barbatdev
barbatdev merged commit 864e667 into main Nov 12, 2026
3 checks passed
@barbatdev
barbatdev deleted the fix/358-uninstall-missing-root branch November 12, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Corrección: feat(lifecycle): update and uninstall directory targets via recorded ownership (#354)

1 participant