Skip to content

feat!: standardize co CLI on --dry-run and --timeout#28

Merged
clawd131662[bot] merged 2 commits into
masterfrom
feat/co-cli-ergonomics
Jul 8, 2026
Merged

feat!: standardize co CLI on --dry-run and --timeout#28
clawd131662[bot] merged 2 commits into
masterfrom
feat/co-cli-ergonomics

Conversation

@clawd131662

@clawd131662 clawd131662 Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Stacked on #27 (feat/co-trim). Review/merge #27 first; this PR's base
is feat/co-trim, and the diff below is only the two ergonomics commits.
GitHub will retarget it to master automatically once #27 merges.

Why

With --dry-run available on every command, the interactive --yes/-y
confirmation prompt is redundant and blocks unattended (cron) runs. Separately,
the .env TIMEOUT of 10 s kills long-running statements on cold caches — the
co:purge_orphaned_entities NOT EXISTS batches were observed being killed at
10 s — so every command needs a per-run override.

What

Two cross-cutting changes that standardize the CLI across co:purge,
co:purge_orphaned_entities, and co:trim:

  1. feat!: drop --yes prompts in favor of --dry-run — removes the
    --yes/-y flag and all interactive confirmation. Commands now print the
    scan estimate and execute immediately. --dry-run becomes the uniform
    preview mechanism: co:purge and co:purge_orphaned_entities gain it
    (counting instead of deleting), and every dry run summarizes with
    "Would purge/trim total N rows."

  2. feat: support --timeout on all commands — generalizes co:trim's
    session max_statement_time override (--timeout, default 600 s) to
    co:purge and co:purge_orphaned_entities via a shared
    apply_session_timeout.

⚠ Breaking change

--yes/-y is removed. Any script or cron job passing -y/--yes must drop
it. Commands no longer prompt — they act immediately; use --dry-run to preview
first.

Review fixes applied

  • Legacy rake prompts: dropping the interactive prompt removed two i18n keys
    that the legacy block:purge rake task still uses (record_deletion_prompt,
    prompt_canceled_message). Both are retained in en.yml (with a comment) so
    block:purge keeps working; the unused orphaned_deletion_prompt /
    trim_scan_prompt stay removed.
  • Dry-run batch off-by-one: the batch window is now r1..(r1 + step - 1)
    (half-open), so consecutive --dry-run batches no longer double-count the row
    on each boundary. purge_proc also drops a duplicated Block.where(...)
    build in the process.

Test plan

  • co:purge_orphaned_entities --dry-run now completes under the default
    --timeout=600 (previously killed at the 10 s .env TIMEOUT).
  • co:purge / co:trim dry-run smoke tests pass.
  • rubocop clean apart from the pre-existing Metrics/ClassLength offense.

🤖 Generated with Claude Code

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review below. One cross-file breakage worth addressing before merge, plus a minor dry-run accuracy nit.

Comment thread config/locales/en.yml
Comment thread co.thor
@claude

claude Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review summary

Nice, coherent cleanup — standardizing on --dry-run + --timeout across all three commands is the right direction, the dry-run wiring in co.thor is consistent (count instead of delete, distinct "would…" locale keys, checkpoint/logger skipped under dry-run), and the docs (CLAUDE.md / README / hot-coordinate-trim.md) are kept in sync. Consolidating apply_trim_timeout → shared apply_session_timeout reads well.

Two things worth a look:

  1. (worth fixing) Removed locale keys are still referenced by block:purge. record_deletion_prompt and prompt_canceled_message are deleted from en.yml but lib/tasks/block.rake still uses both. There's no raise_on_missing config, so it won't crash — it'll print translation missing: … — but the legacy task's confirmation prompt is now broken. Either restore the two keys or (cleaner, since CLAUDE.md marks these rake purges as superseded by co:purge) retire that prompt path in this PR.

  2. (minor) Dry-run over-counts batch-boundary rows. Inclusive rowid: r1..r2 with r2 = r1 + step and a step-strided loop double-counts the boundary row in purge_proc/purge_orphaned_proc. Harmless in the real delete path (row is gone before the next batch), but it makes "Would purge total N rows" slightly overstate the real result. r2 = r1 + limit_param - 1 fixes it.

On the breaking change itself (dropping --yes / interactive confirmation on a destructive prod tool): the rationale is sound and well-documented, and --dry-run is a reasonable replacement for cron. Just make sure the existing cron entries that pass -y are updated when this ships, since they'll now error on the unknown flag.

@shikendon
shikendon force-pushed the feat/co-cli-ergonomics branch from 5bd8716 to 9e21a2e Compare July 8, 2026 14:09
@claude

claude Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review summary

Clean, focused follow-up. Both concerns from the previous round are addressed, and I've resolved those threads:

  • Legacy locale keysrecord_deletion_prompt and prompt_canceled_message are retained (with a comment noting they serve block:purge), so lib/tasks/block.rake keeps working. The genuinely-unused orphaned_deletion_prompt / trim_scan_prompt are correctly dropped.
  • Dry-run boundary off-by-one — batch windows are now half-open (rowid: r1..(r1 + step - 1) in purge_proc, r2 = r1 + orphaned_limit_param - 1 in purge_orphaned_proc), so consecutive dry-run batches no longer double-count the boundary row.

The rest reads well: --dry-run wiring is consistent across all three commands (count instead of delete, distinct would_* locale keys, logger skipped under dry-run), apply_trim_timeout → shared apply_session_timeout is a nice consolidation, and CLAUDE.md / README are kept in sync. No dangling references to the removed continue?/yes?/confirm? helpers.

One operational reminder (already noted last round, not a code issue): dropping --yes/-y means any existing cron entry passing that flag will now error on the unknown option — update those when this ships. Otherwise LGTM.

Note: this PR is stacked on #27 (feat/co-trim); merge that first.

@shikendon
shikendon force-pushed the feat/co-cli-ergonomics branch from 9e21a2e to c48c283 Compare July 8, 2026 14:15

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review summary

Third pass — verifying the fixes from the prior rounds hold. They do, and I don't find anything new worth changing.

Confirmed resolved:

  • Legacy locale keysrecord_deletion_prompt / prompt_canceled_message are retained in en.yml (with a comment pointing at block:purge), and lib/tasks/block.rake:17,37 still resolves both. The genuinely-unused orphaned_deletion_prompt / trim_scan_prompt are correctly dropped, and no other rake task references them.
  • Dry-run boundary off-by-one — windows are now half-open (rowid: r1..(r1 + limit_param - 1) in purge_proc, r2 = r1 + orphaned_limit_param - 1 in purge_orphaned_proc) with a matching step stride, so consecutive dry-run batches no longer double-count the boundary row. Dry-run counts now match the real delete path.

Also checked, all clean: no dangling references to the removed continue?/confirm?/yes?/apply_trim_timeout helpers; every I18n key used by co.thor resolves; the scope-reuse in purge_proc is correct (lazy relation, independent .first/.count/.delete_all queries); apply_trim_timeout → shared apply_session_timeout reads well and is now applied under --dry-run too (desirable — dry-run scans can also run long); and CLAUDE.md / README are kept in sync.

One operational reminder (not a code issue, and unchanged since round one): dropping --yes/-y is a breaking change — any cron entry or script still passing that flag will now error on the unknown option, and bin/thor co:purge with no --dry-run deletes immediately with no confirmation. The rationale (unattended cron + --dry-run as the preview mechanism) is sound and well-documented; just make sure the existing cron entries are updated when this ships. Note this is stacked on #27 (feat/co-trim) — merge that first.

LGTM.

claude added 2 commits July 8, 2026 15:02
Remove the --yes/-y flag and interactive confirmation from all
commands; they now print the scan estimate and execute immediately.
--dry-run becomes the uniform preview mechanism: co:purge and
co:purge_orphaned_entities gain it (counting instead of deleting),
and all dry runs summarize with "Would purge/trim total N rows."

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rxDnL4R89uo579K66Gtbd
Generalize co:trim's session max_statement_time override
(apply_session_timeout, default 600 s) to co:purge and
co:purge_orphaned_entities; the orphaned-entities NOT EXISTS batches
were observed being killed by the 10 s .env TIMEOUT on cold caches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rxDnL4R89uo579K66Gtbd
@shikendon
shikendon force-pushed the feat/co-cli-ergonomics branch from c48c283 to 0ae2be4 Compare July 8, 2026 15:03
@claude

claude Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review summary

Fourth pass, focused on anything the prior rounds didn't cover. Nothing new worth fixing — the change is clean and both previously-raised issues remain correctly resolved.

Verified this pass:

  • Batch tiling is exact in both paths. purge_proc (rowid: r1..(r1 + limit_param - 1)) and purge_orphaned_proc (r2 = r1 + orphaned_limit_param - 1) now tile contiguously with a matching step stride — no overlap, no gap. Since ranges are disjoint by rowid, deleting batch N never shifts batch N+1's window, so the dry-run count (scope.count / orphaned_ids.size) equals what the real delete_all returns. The "Would purge total N rows" preview is now faithful.
  • scope reuse in purge_proc is sound — lazy relation, independent .first / .count / .delete_all queries; the dropped duplicate Block.where(...) build is a genuine cleanup.
  • apply_session_timeout consolidation is correct and safe. Shared across all three commands, applied under --dry-run too (desirable — scans can run long), and Integer(options[:timeout]) coerces the numeric option so the raw SET SESSION is injection-safe.
  • No dangling references to the removed --yes/-y, continue?/confirm?/yes?, continue_trim?/continue_orphaned?, or apply_trim_timeout. The retained record_deletion_prompt / prompt_canceled_message keys are still resolved by lib/tasks/block.rake:17,37; the genuinely-unused prompt keys are correctly dropped. Every I18n key used by co.thor resolves.
  • Docs in sync — CLAUDE.md (shared --timeout note + per-command --dry-run) and README (co:purge help block + example) match the new CLI surface.

One operational reminder (unchanged, not a code issue): dropping --yes/-y is breaking — any cron entry or script still passing that flag will now error on the unknown option, and co:purge with no --dry-run deletes immediately with no confirmation. The rationale (unattended cron + --dry-run preview) is sound and well-documented; just update the existing cron entries when this ships. Note this is stacked on #27 (feat/co-trim, still open) — merge that first.

LGTM.

@shikendon
shikendon deleted the branch master July 8, 2026 15:09
@shikendon shikendon closed this Jul 8, 2026
@clawd131662 clawd131662 Bot reopened this Jul 8, 2026
@clawd131662
clawd131662 Bot changed the base branch from feat/co-trim to master July 8, 2026 15:11
@claude

claude Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review summary (independent pass)

LGTM. Standardizing the CLI on --dry-run + --timeout across co:purge, co:purge_orphaned_entities, and co:trim is a coherent, well-scoped change, and both previously-raised threads are correctly resolved:

  • Legacy locale keysrecord_deletion_prompt / prompt_canceled_message are retained (with a comment) and remain the only i18n keys lib/tasks/block.rake needs; container.rake/entity.rake use no i18n keys, so nothing else is left half-wired. The unused orphaned_deletion_prompt / trim_scan_prompt are correctly dropped.
  • Dry-run boundary off-by-one — half-open windows (rowid: r1..(r1 + limit_param - 1), r2 = r1 + orphaned_limit_param - 1) with a matching step stride tile disjointly by rowid, so dry-run counts (scope.count / orphaned_ids.size) equal what delete_all would return. Deleting entities can't change other entities' orphaned status (the scope keys off co_block), so the orphaned dry-run count is faithful too.

Also verified: apply_session_timeout consolidation is correct and injection-safe (Integer(options[:timeout])), applied under dry-run as well; no dangling --yes/continue?/confirm?/yes?/apply_trim_timeout references; README / CLAUDE.md match the new surface.

One operational note (a deliberate, well-documented design choice, not a blocker): dropping --yes means co:purge now deletes immediately with no interactive guard, and any cron/script still passing -y/--yes will error on the unknown flag — update those when this ships. Stacked on #27 — merge that first.

@clawd131662
clawd131662 Bot merged commit 733849f into master Jul 8, 2026
2 checks passed
@shikendon
shikendon deleted the feat/co-cli-ergonomics branch July 8, 2026 15:15
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.

2 participants