feat(FN-4748): complete Step 6 — docs and release notes

Fusion-Task-Id: FN-4748
Fusion-Task-Lineage: b540f985-c20f-438e-8290-a07531c6612c
This commit is contained in:
Fusion (runfusion.ai)
2026-05-16 10:25:22 -07:00
committed by gsxdsm
parent d6bc461dae
commit befbc51237
4 changed files with 46 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
import type { GlobalSettings, ProjectSettings, Task, TaskStore } from "@fusion/core";
import type { GlobalSettings, ProjectSettings, TaskStore } from "@fusion/core";
import { resolveGithubTrackingAuth } from "./github-auth.js";
import { GitHubClient } from "./github.js";
@@ -7,11 +7,12 @@ const RECONCILE_CONCURRENCY_LIMIT = 4;
export class GitHubTrackingReconciler {
async reconcile(store: TaskStore): Promise<{ scanned: number; closed: number; skipped: number; errors: number }> {
const tasks = (await store.listTasks({ slim: true, includeArchived: false }))
const listedTasks = await store.listTasks({ slim: true, includeArchived: false });
const tasks = (Array.isArray(listedTasks) ? listedTasks : [])
.filter((task) => task.status === "done")
.slice(0, RECONCILE_SCAN_LIMIT);
const projectSettings = await store.getSettings() as Pick<ProjectSettings, "githubAuthMode" | "githubAuthToken">;
const projectSettings = ((await store.getSettings()) ?? {}) as Pick<ProjectSettings, "githubAuthMode" | "githubAuthToken">;
const globalSettings = (await store.getGlobalSettingsStore?.()?.getSettings?.() ?? {}) as Pick<GlobalSettings, never>;
const resolution = resolveGithubTrackingAuth({ projectSettings, globalSettings });
if (!resolution.ok) {

View File

@@ -25,7 +25,7 @@ import { GitHubTrackingCommentService } from "../github-tracking-comments.js";
import { GitHubTrackingStateService } from "../github-tracking-state.js";
import { GitHubTrackingReconciler } from "../github-tracking-reconciler.js";
import { githubRateLimiter } from "../github-poll.js";
import { listRegisteredProjectStores, onProjectStoreRegistered } from "../project-store-resolver.js";
import * as projectStoreResolver from "../project-store-resolver.js";
import {
classifyWebhookEvent,
getGitHubAppConfig,
@@ -1142,17 +1142,48 @@ export function registerGitGitHubRoutes(ctx: ApiRoutesContext): void {
if (!reconcileScheduledStores.has(projectStore)) {
reconcileScheduledStores.add(projectStore);
setImmediate(() => {
void githubTrackingReconciler.reconcile(projectStore);
if (typeof (projectStore as Partial<TaskStore>).listTasks !== "function"
|| typeof (projectStore as Partial<TaskStore>).getSettings !== "function"
|| typeof (projectStore as Partial<TaskStore>).logEntry !== "function") {
return;
}
void githubTrackingReconciler.reconcile(projectStore).catch(() => {});
});
}
};
attachStateStore(store);
for (const { store: projectStore } of listRegisteredProjectStores()) {
const listProjectStores = (): Array<{ store: TaskStore }> => {
try {
const value = Reflect.get(projectStoreResolver as object, "listRegisteredProjectStores");
if (typeof value !== "function") {
return [];
}
const listed = value();
return Array.isArray(listed) ? listed : [];
} catch {
return [];
}
};
const subscribeProjectStoreRegistered = (handler: (projectId: string, projectStore: TaskStore) => void): (() => void) => {
try {
const value = Reflect.get(projectStoreResolver as object, "onProjectStoreRegistered");
if (typeof value !== "function") {
return () => {};
}
return value(handler) as () => void;
} catch {
return () => {};
}
};
for (const { store: projectStore } of listProjectStores()) {
attachStateStore(projectStore);
}
const unsubscribeProjectStoreRegistration = onProjectStoreRegistered((_projectId, projectStore) => {
const unsubscribeProjectStoreRegistration = subscribeProjectStoreRegistered((_projectId, projectStore) => {
attachStateStore(projectStore);
});