remove review badges, add help page, auto-rename noop items
Build and Push Docker Image / build (push) Successful in 1m52s

Three threads:

1. Drop the " Auto-approve" / " Needs decision" pills on PipelineCard
   and the "N auto · M need decisions" subtitle on ReviewColumn — noise
   for a workflow that wants to be unattended. Card amber tint stays as
   a softer cue. Remove the now-unused reviewManualCount field on the
   pipeline payload.

2. New /help route in the nav. Documents what netfelix actually does
   end-to-end, the folder/SxxExx/ID brackets we require, and that the
   codec/quality/audio brackets are *arr's job — we trigger their rename
   API instead of parsing them ourselves. Links to TRaSH guides.

3. Refactor triggerMovieRename / triggerSeriesRename to return a
   basename → new-basename map instead of one path. Add a batched
   triggerRenameFor in execute.ts that dedupes by movie and by series
   (one Sonarr call covers every episode of a series). Hook into
   processInbox: when an item becomes noop, fire a rename pass so
   lying filenames on already-clean files self-heal. Idempotent —
   *arr returns no work to do when names already match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 08:14:10 +02:00
parent 0e2f027f7a
commit 5d0af08b79
12 changed files with 261 additions and 119 deletions
+12 -4
View File
@@ -29,6 +29,7 @@ import {
emitInboxSortStart,
emitPipelineChanged,
maybeStartQueueProcessor,
triggerRenameForItems,
} from "./execute";
const app = new Hono();
@@ -172,6 +173,7 @@ export async function processInbox(
let movedToQueue = 0;
let movedToReview = 0;
let processed = 0;
const becameNoop: number[] = [];
for (const { item_id } of unsortedIds) {
if (hooks?.signal?.aborted) break;
@@ -214,9 +216,13 @@ export async function processInbox(
db.prepare("UPDATE review_plans SET sorted = 1 WHERE id = ?").run(plan.id);
movedToReview += 1;
}
} else if (plan?.is_noop) {
// Item went straight to "done" without a job. Its filename may still
// be lying about codecs/channels/quality — give *arr a chance to
// rename it. Idempotent if the name already matches the pattern.
becameNoop.push(item_id);
}
// plans that vanished (!plan) or became noops fall through — the
// is_noop filter already excludes them from both Inbox and Review.
// plans that vanished (!plan) fall through.
processed += 1;
hooks?.onProgress?.(processed, total);
@@ -227,6 +233,10 @@ export async function processInbox(
}
log(`processInbox complete: ${movedToQueue} → queue, ${movedToReview} → review, ${total - processed} skipped`);
if (becameNoop.length > 0) {
log(`processInbox: triggering rename for ${becameNoop.length} new noop items`);
triggerRenameForItems(becameNoop);
}
return { moved_to_queue: movedToQueue, moved_to_review: movedToReview };
}
@@ -839,7 +849,6 @@ app.get("/pipeline", (c) => {
)
.get() as { n: number }
).n;
const reviewManualCount = reviewItemsTotal - reviewReadyCount;
const autoProcessing = getConfig("auto_processing") === "1";
const autoProcessQueue = getConfig("auto_process_queue") === "1";
@@ -906,7 +915,6 @@ app.get("/pipeline", (c) => {
inboxTotal,
reviewItemsTotal,
reviewReadyCount,
reviewManualCount,
autoProcessing,
autoProcessQueue,
queued,