From a24522437cd94daa54ccee358806d63bc3b1758b Mon Sep 17 00:00:00 2001 From: Shaheer Sarfaraz <53654735+DaKheera47@users.noreply.github.com> Date: Sun, 8 Feb 2026 15:12:54 +0000 Subject: [PATCH] manual import should move to ready directly (#109) --- .../client/components/ManualImportFlow.tsx | 2 +- .../src/client/pages/OrchestratorPage.tsx | 2 +- .../src/server/api/routes/manual-jobs.test.ts | 2 + .../src/server/api/routes/manual-jobs.ts | 37 ++++++++++++++++--- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/orchestrator/src/client/components/ManualImportFlow.tsx b/orchestrator/src/client/components/ManualImportFlow.tsx index a6f3f3d..5d637b4 100644 --- a/orchestrator/src/client/components/ManualImportFlow.tsx +++ b/orchestrator/src/client/components/ManualImportFlow.tsx @@ -216,7 +216,7 @@ export const ManualImportFlow: React.FC = ({ const payload = toPayload(draft); const created = await api.importManualJob({ job: payload }); toast.success("Job imported", { - description: "The job is now in the discovered column.", + description: "The job was tailored and moved to the ready column.", }); await onImported(created.id); onClose(); diff --git a/orchestrator/src/client/pages/OrchestratorPage.tsx b/orchestrator/src/client/pages/OrchestratorPage.tsx index 65deb13..f3f0975 100644 --- a/orchestrator/src/client/pages/OrchestratorPage.tsx +++ b/orchestrator/src/client/pages/OrchestratorPage.tsx @@ -177,7 +177,7 @@ export const OrchestratorPage: React.FC = () => { const handleManualImported = useCallback( async (importedJobId: string) => { await loadJobs(); - navigateWithContext("discovered", importedJobId); + navigateWithContext("ready", importedJobId); }, [loadJobs, navigateWithContext], ); diff --git a/orchestrator/src/server/api/routes/manual-jobs.test.ts b/orchestrator/src/server/api/routes/manual-jobs.test.ts index 67670ac..866c1d5 100644 --- a/orchestrator/src/server/api/routes/manual-jobs.test.ts +++ b/orchestrator/src/server/api/routes/manual-jobs.test.ts @@ -63,6 +63,7 @@ describe.sequential("Manual jobs API routes", () => { }); it("imports manual jobs and generates a fallback URL", async () => { + const { processJob } = await import("../../pipeline/index"); const { scoreJobSuitability } = await import("../../services/scorer"); vi.mocked(scoreJobSuitability).mockResolvedValue({ score: 88, @@ -84,6 +85,7 @@ describe.sequential("Manual jobs API routes", () => { expect(body.ok).toBe(true); expect(body.data.source).toBe("manual"); expect(body.data.jobUrl).toMatch(/^manual:\/\//); + expect(vi.mocked(processJob)).toHaveBeenCalledWith(body.data.id); await new Promise((resolve) => setTimeout(resolve, 25)); }); }); diff --git a/orchestrator/src/server/api/routes/manual-jobs.ts b/orchestrator/src/server/api/routes/manual-jobs.ts index b91c029..644ba9c 100644 --- a/orchestrator/src/server/api/routes/manual-jobs.ts +++ b/orchestrator/src/server/api/routes/manual-jobs.ts @@ -8,6 +8,7 @@ import type { import { type Request, type Response, Router } from "express"; import { JSDOM } from "jsdom"; import { z } from "zod"; +import { processJob } from "../../pipeline/index"; import * as jobsRepo from "../../repositories/jobs"; import { inferManualJobDetails } from "../../services/manualJob"; import { getProfile } from "../../services/profile"; @@ -234,6 +235,26 @@ manualJobsRouter.post("/import", async (req: Request, res: Response) => { starting: cleanOptional(job.starting) ?? undefined, }); + const processResult = await processJob(createdJob.id); + if (!processResult.success) { + logger.warn("Manual job auto-processing failed", { + jobId: createdJob.id, + error: processResult.error ?? "Unknown error", + }); + return res.status(502).json({ + success: false, + error: + processResult.error || + "Imported job but failed to move it to ready automatically", + details: { jobId: createdJob.id }, + }); + } + + const processedJob = await jobsRepo.getJobById(createdJob.id); + if (!processedJob) { + return res.status(404).json({ success: false, error: "Job not found" }); + } + // Score asynchronously so the import returns immediately. (async () => { try { @@ -247,21 +268,27 @@ manualJobsRouter.post("/import", async (req: Request, res: Response) => { } const profile = rawProfile as Record; const { score, reason } = await scoreJobSuitability( - createdJob, + processedJob, profile, ); - await jobsRepo.updateJob(createdJob.id, { + await jobsRepo.updateJob(processedJob.id, { suitabilityScore: score, suitabilityReason: reason, }); } catch (error) { - logger.warn("Manual job scoring failed", error); + logger.warn("Manual job scoring failed", { + jobId: processedJob.id, + error, + }); } })().catch((error) => { - logger.warn("Manual job scoring task failed to start", error); + logger.warn("Manual job scoring task failed to start", { + jobId: processedJob.id, + error, + }); }); - res.json({ success: true, data: createdJob }); + res.json({ success: true, data: processedJob }); } catch (error) { if (error instanceof z.ZodError) { return res.status(400).json({ success: false, error: error.message });