Files
fusion/plugins/fusion-plugin-reports/src/pipeline.ts
Fusion 8089953710 feat(FN-3860): add cadence resolution seam (+7 more)
Commits merged:
- feat(FN-3860): complete Step 8 — documentation and delivery
- test(FN-3860): complete Step 7 — add scaffold seam coverage
- feat(FN-3860): complete Step 6 — re-export scaffold seams
- feat(FN-3860): complete Step 5 — add pipeline orchestrator seam
- feat(FN-3860): complete Step 4 — add in-memory runs store seam
- feat(FN-3860): complete Step 3 — add aggregation seam
- feat(FN-3860): complete Step 2 — add cadence resolution seam
- feat(FN-3846): short-circuit phantom merges for already-landed branches

Files changed:
.changeset/fn-3860-reports-scaffold-files.md       |  5 ++
 plugins/fusion-plugin-reports/README.md            |  9 +++
 .../src/__tests__/scaffold.test.ts                 | 60 +++++++++++++++++++
 plugins/fusion-plugin-reports/src/aggregation.ts   | 23 ++++++++
 plugins/fusion-plugin-reports/src/cadence.ts       | 23 ++++++++
 plugins/fusion-plugin-reports/src/index.ts         |  4 ++
 plugins/fusion-plugin-reports/src/pipeline.ts      | 58 ++++++++++++++++++
 plugins/fusion-plugin-reports/src/runs-store.ts    | 69 ++++++++++++++++++++++
 8 files changed, 251 insertions(+)

Fusion-Task-Id: FN-3860
2026-05-11 08:02:53 -07:00

59 lines
1.8 KiB
TypeScript

/**
* INTERIM ORCHESTRATOR. FN-3779 replaces this with cadence-registry + cron-sentinel wiring;
* FN-3780 replaces the aggregate dependency with the real aggregation layer.
* Keep the `ReportsPipelineDependencies` shape stable so both can plug in without callsite churn.
*/
import type { ReportsAggregator } from "./aggregation.js";
import type { ReportsCadence } from "./cadence.js";
import type { ReportRunRecord, ReportsRunsStore } from "./runs-store.js";
export interface ReportsPipelineDependencies {
runsStore: ReportsRunsStore;
aggregate: ReportsAggregator;
}
export interface StartPipelineInput {
runId: string;
cadence: ReportsCadence;
settings: Record<string, unknown>;
now?: Date;
}
export async function startReportsPipeline(
input: StartPipelineInput,
deps: ReportsPipelineDependencies,
): Promise<ReportRunRecord> {
const nowIso = (input.now ?? new Date()).toISOString();
const created = await deps.runsStore.create({
id: input.runId,
cadence: input.cadence,
status: "queued",
createdAt: nowIso,
updatedAt: nowIso,
});
await deps.runsStore.update(input.runId, { status: "running", updatedAt: nowIso });
try {
await deps.aggregate({
runId: input.runId,
cadence: input.cadence,
settings: input.settings,
});
const updatedAt = new Date().toISOString();
const reviewed = await deps.runsStore.update(input.runId, { status: "review", updatedAt });
return reviewed ?? { ...created, status: "review", updatedAt };
} catch (error) {
const updatedAt = new Date().toISOString();
const message = error instanceof Error ? error.message : String(error);
const failed = await deps.runsStore.update(input.runId, {
status: "failed",
error: message,
updatedAt,
});
return failed ?? { ...created, status: "failed", error: message, updatedAt };
}
}