Skip to content

feat: prune orphaned missing_path inventory rows#870

Merged
chubes4 merged 6 commits into
mainfrom
fix-inventory-prune-missing
Jul 6, 2026
Merged

feat: prune orphaned missing_path inventory rows#870
chubes4 merged 6 commits into
mainfrom
fix-inventory-prune-missing

Conversation

@chubes4

@chubes4 chubes4 commented Jul 5, 2026

Copy link
Copy Markdown
Member

What this does

Adds a non-SQL path to reap orphaned missing_path=1 rows from the DB-backed workspace inventory (c8c_datamachine_code_worktrees). When a primary checkout directory is deleted from disk, its row becomes an unreachable ghost — inventory refresh flags it and hygiene counts it, but nothing ever deleted it, and workspace remove <handle> structurally cannot (it resolves handles from disk). The only fix was manual SQL.

New CLI:

wp datamachine-code workspace inventory prune-missing [--dry-run] [--yes] [--force] [--format=<format>]

Backed by a new ability datamachine-code/workspace-worktree-inventory-prune-missing.

Flags

  • --dry-run — Preview candidates and skips without deleting anything.
  • --yes — Skip the confirmation prompt (a dry-run preview is shown before any real deletion unless --yes is passed).
  • --force — Allow pruning rows with unpushed_count > 0 or a non-empty pr_url (otherwise they are skipped and reported).
  • --formattable (default) or json.

Safety guards

  1. Re-probe (never trusts a stale flag). Before deleting, each candidate row's path is re-probed on disk. Only rows whose path is still absent are deleted. A row flagged missing_path=1 whose directory came back is skipped (reason: path_present_on_disk).
  2. Unpushed / PR protection. Rows with unpushed_count > 0 or a non-empty pr_url are skipped unless --force is passed (skip reasons: unpushed_count, pr_url).
  3. Confirmation. A real (non-dry-run) run shows a dry-run preview and prompts unless --yes is set. If nothing would be deleted, it short-circuits with a success message.

Success output mirrors the terse refresh style: Inventory pruned: N deleted, M skipped. (or (dry-run) variant).

Files changed and why

  • inc/Storage/WorktreeInventoryRepository.php — New pruneMissing(array $opts): array storage primitive that fetches missing_path=1 rows (via private missing_path_rows() helper using a targeted WHERE missing_path = 1 query that hits the existing index), re-probes disk, applies unpushed/PR guards, deletes survivors, and returns a summary with deleted/skipped lists. Reuses the existing delete() / table_name() / decode_row() patterns in the class.
  • inc/Workspace/WorkspaceWorktreeLifecycle.php — Thin public wrapper worktree_inventory_prune_missing(array $opts) mirroring worktree_inventory_refresh(), delegating to the repository via the existing worktree_inventory() accessor.
  • inc/Abilities/WorkspaceAbilities.php — Registers datamachine-code/workspace-worktree-inventory-prune-missing (same shape/permission/schema conventions as the sibling -refresh ability) and adds the worktreeInventoryPruneMissing() execute callback.
  • inc/Cli/Commands/WorkspaceCommand.php — Splits the inventory op handler into refresh/prune-missing dispatchers, adds the prune-missing handler with --dry-run/--yes/--force/--format handling and a confirmation flow, and updates the docblock/usage string so prune-missing is documented.
  • tests/worktree-inventory-prune-missing.php — New standalone smoke test (5 cases).

Test results

This repo uses standalone PHP smoke tests under tests/ (no PHPUnit). New test added and passing:

$ php tests/worktree-inventory-prune-missing.php
worktree-inventory-prune-missing OK — 5/5 passed

Cases covered:

  1. --dry-run returns candidates without deleting (rows remain in store).
  2. Re-probe guard skips rows whose path is present on disk (stale missing_path=1 flag not trusted).
  3. unpushed_count > 0 and non-empty pr_url are skipped without --force.
  4. --force overrides the unpushed/PR guards.
  5. Rows flagged missing_path=0 are never considered as candidates.

Existing related smoke tests still green (json-codec, workspace-handle). PHP lint clean on all 4 changed source files.

Judgment-call forks

  • Where the safety logic lives. Put the full re-probe + skip-guard + delete logic in the repository pruneMissing() primitive (rather than the Workspace/CLI layer). Rationale: the issue explicitly asked for a pruneMissing() storage primitive that "returns a summary", the repository already encodes disk-reconciliation semantics (mark_missing() / missing_path / build_worktree_inventory_row_from_handle), and keeping it in one place makes it unit-testable without a WP stack. The Workspace method is a one-line delegate, exactly like worktree_inventory_refresh().
  • Confirmation flow. A real run does a dry-run preview first, shows the would-delete/would-skip counts, then prompts (skippable via --yes). --dry-run alone never prompts. If zero rows would be deleted, it short-circuits with success before prompting. This follows the existing workspace remove --yes confirmation convention while giving operators visibility into what a destructive run will touch.
  • SQL filter placement. Candidates are fetched with a targeted WHERE missing_path = 1 (uses the existing missing_path key) rather than pulling all rows and filtering in PHP. The smoke-test $wpdb stub honors the predicate so the production SQL path is exercised faithfully.

Closes #869.

Add `workspace inventory prune-missing` and the
`datamachine-code/workspace-worktree-inventory-prune-missing` ability to
reap ghost rows whose on-disk directory was deleted.

Safety guards:
- Re-probes each candidate's path; only deletes when STILL absent.
- Refuses rows with unpushed_count > 0 or non-empty pr_url unless --force.
- --dry-run previews candidates and skips without mutating.

Closes #869.
@homeboy-ci

homeboy-ci Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Homeboy Results — data-machine-code

Lint

review lint — passed

ℹ️ Full options: homeboy self docs commands/lint
Deep dive: homeboy review lint data-machine-code --changed-since 45f4d34

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-code-review-lint-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-code-review-lint-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine-code/actions/runs/28764497971

Test

review test — passed

ℹ️ Auto-fix lint issues: homeboy refactor data-machine-code --from lint --write
ℹ️ Collect coverage: homeboy test data-machine-code --coverage
ℹ️ Save test baseline: homeboy test data-machine-code --baseline
ℹ️ Pass args to test runner: homeboy test -- [args]
ℹ️ Full options: homeboy self docs commands/test
Deep dive: homeboy review test data-machine-code --changed-since 45f4d34

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-code-review-test-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-code-review-test-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine-code/actions/runs/28764497971

Audit

review audit — passed

  • audit — 22 finding(s)
  • Total: 22 finding(s)

Deep dive: homeboy review audit data-machine-code --changed-since 45f4d34

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-code-review-audit-quality-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-code-review-audit-quality-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine-code/actions/runs/28764497971
Tooling versions
  • Homeboy CLI: homeboy 0.281.14+dde84b2f9d55+c84b18c
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: 68d84557
  • Action: unknown@unknown

@chubes4 chubes4 merged commit 883b8df into main Jul 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

workspace inventory: no way to prune orphaned missing_path=1 rows (dead primaries linger, require manual SQL)

1 participant