Skip to content

Execute Clean from cached ScanPlan (add cleanFromPlan)#9

Merged
Therosin merged 3 commits intodevelopfrom
codex/implement-consistent-approach-in-main.ts-and-logic.ts
Mar 1, 2026
Merged

Execute Clean from cached ScanPlan (add cleanFromPlan)#9
Therosin merged 3 commits intodevelopfrom
codex/implement-consistent-approach-in-main.ts-and-logic.ts

Conversation

@Therosin
Copy link
Member

@Therosin Therosin commented Mar 1, 2026

Motivation

  • Ensure Clean operates on an explicitly reviewed, previously produced ScanPlan so the UI can guarantee the plan applied is the plan the user inspected.
  • Prevent surprises from mid-flight recomputation by requiring the scanned root, active keeplist, and chosen clean mode to match the cached plan before allowing Clean to proceed.

Description

  • Added cleanFromPlan(root, plan, options) and CleanFromPlanOptions in logic.ts and made cleanFolderDetailed delegate to it so clean execution can be driven from a ScanPlan without recomputing.
  • Implemented plan-based execution semantics in cleanFromPlan, preserving deterministic removal ordering, quarantine handling, rename ordering, and existing rename outcome semantics.
  • Updated main.ts to cache the last scan context (lastScanPlan, lastScannedRoot, lastScannedKeeplistName, lastScannedMode), invalidate the cache when inputs change (including mode changes via markScanDirty()), and require a matching cached plan before permitting Clean.
  • Added tests in logic_test.ts verifying that cleanFromPlan executes only the previously built plan (leaving files created after the scan untouched) and that invalid mode values are rejected.

Testing

  • Ran deno fmt main.ts logic.ts logic_test.ts successfully to normalize formatting.
  • Attempted deno task test but the test run failed in this environment due to an external dependency fetch error fetching JSR metadata for @std/assert, so the updated test suite could not be executed here; test cases were added to logic_test.ts to cover the new contract.

Codex Task

Copilot AI review requested due to automatic review settings March 1, 2026 14:43
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75c9c80c72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +914 to +916
lastScannedRoot !== root ||
lastScannedKeeplistName !== keeplistName ||
lastScannedMode !== mode

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Re-validate keeplist before applying cached clean plan

cleanFiles now gates execution only on cached root/name/mode and then runs cleanFromPlan, but it no longer verifies that the active keeplist file still exists and has keep rules at clean time. After a successful scan, deleting or emptying the keeplist still allows cleanup to proceed from the stale plan, whereas the previous cleanFolderDetailed path re-ran buildScanPlan and raised explicit keeplist errors. This regresses the documented safety behavior for missing/empty keeplists and can apply destructive removals under invalid current config.

Useful? React with 👍 / 👎.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the ability to execute a previously generated ScanPlan deterministically (without recomputing) so the UI can ensure “the plan applied is the plan the user reviewed,” and gates Clean on a matching cached scan context.

Changes:

  • Introduces cleanFromPlan(root, plan, options) and updates cleanFolderDetailed to delegate to it.
  • Updates the UI flow to cache the last ScanPlan + scan inputs (root / keeplist / mode) and require a match before allowing Clean.
  • Adds tests to ensure cleanFromPlan executes exactly the cached plan and validates clean mode values.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
main.ts Caches last scan plan/context and requires an exact match before running Clean; invalidates cache when inputs change.
logic.ts Adds cleanFromPlan and routes existing clean execution through it.
logic_test.ts Adds coverage for plan-based execution and invalid clean mode rejection.
Comments suppressed due to low confidence (1)

logic.ts:575

  • With plan-based execution there can be a longer gap between scan and clean, so individual files in plan.removableFiles may legitimately be missing by the time cleanFromPlan runs. Consider treating Deno.errors.NotFound during per-file delete/quarantine as a no-op (continue cleaning) so one missing file doesn't abort the entire run.
  const mode = options.mode ?? "delete";

  if (mode !== "delete" && mode !== "quarantine") {
    throw new Error(`Invalid clean mode: ${mode}`);
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +566 to +570
export async function cleanFromPlan(
root: string,
plan: ScanPlan,
options: CleanFromPlanOptions = {},
): Promise<CleanResult> {
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because cleanFromPlan is exported and accepts a ScanPlan from callers, it should defensively validate that plan.removableFiles and plan.plannedRenames contain only clean relative paths (no absolute paths, no .. segments) before executing filesystem operations. Without this, a crafted plan could cause path traversal (deleting/renaming outside root).

Copilot uses AI. Check for mistakes.
@Therosin
Copy link
Member Author

Therosin commented Mar 1, 2026

Addressed locally and pushed in 8c450d5.

The follow-up keeps the cached-plan feature but moves the safety enforcement back into logic.ts, which is where these invariants belong:

  • cleanFromPlan(...) now re-validates the current keeplist before applying a cached plan, so missing/empty keeplists still fail explicitly.
  • exported plan execution still validates incoming paths defensively before any filesystem mutation.
  • stale planned removals that are already gone are treated as no-ops in both delete and quarantine modes, and
    emovedFiles now reports what was actually removed/moved.

Added regression coverage for missing/empty keeplists at clean time and for missing planned removals. deno task test passes locally (69/69).

@Therosin Therosin merged commit 0ca199a into develop Mar 1, 2026
2 checks passed
@Therosin Therosin deleted the codex/implement-consistent-approach-in-main.ts-and-logic.ts branch March 1, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants