Rename Foundry handoffs to tasks (#239)

* Restore foundry onboarding stack

* Consolidate foundry rename

* Create foundry tasks without prompts

* Rename Foundry handoffs to tasks
This commit is contained in:
Nathan Flurry 2026-03-11 13:23:54 -07:00 committed by GitHub
parent d30cc0bcc8
commit d75e8c31d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
281 changed files with 9242 additions and 4356 deletions

View file

@ -1,104 +0,0 @@
import type { HandoffRecord, HandoffStatus } from "@openhandoff/shared";
export const HANDOFF_STATUS_GROUPS = ["queued", "running", "idle", "archived", "killed", "error"] as const;
export type HandoffStatusGroup = (typeof HANDOFF_STATUS_GROUPS)[number];
const QUEUED_STATUSES = new Set<HandoffStatus>([
"init_bootstrap_db",
"init_enqueue_provision",
"init_ensure_name",
"init_assert_name",
"init_create_sandbox",
"init_ensure_agent",
"init_start_sandbox_instance",
"init_create_session",
"init_write_db",
"init_start_status_sync",
"init_complete",
"archive_stop_status_sync",
"archive_release_sandbox",
"archive_finalize",
"kill_destroy_sandbox",
"kill_finalize",
]);
export function groupHandoffStatus(status: HandoffStatus): HandoffStatusGroup {
if (status === "running") return "running";
if (status === "idle") return "idle";
if (status === "archived") return "archived";
if (status === "killed") return "killed";
if (status === "error") return "error";
if (QUEUED_STATUSES.has(status)) return "queued";
return "queued";
}
function emptyStatusCounts(): Record<HandoffStatusGroup, number> {
return {
queued: 0,
running: 0,
idle: 0,
archived: 0,
killed: 0,
error: 0,
};
}
export interface HandoffSummary {
total: number;
byStatus: Record<HandoffStatusGroup, number>;
byProvider: Record<string, number>;
}
export function fuzzyMatch(target: string, query: string): boolean {
const haystack = target.toLowerCase();
const needle = query.toLowerCase();
let i = 0;
for (const ch of needle) {
i = haystack.indexOf(ch, i);
if (i < 0) {
return false;
}
i += 1;
}
return true;
}
export function filterHandoffs(rows: HandoffRecord[], query: string): HandoffRecord[] {
const q = query.trim();
if (!q) {
return rows;
}
return rows.filter((row) => {
const fields = [row.branchName ?? "", row.title ?? "", row.handoffId, row.task, row.prAuthor ?? "", row.reviewer ?? ""];
return fields.some((field) => fuzzyMatch(field, q));
});
}
export function formatRelativeAge(updatedAt: number, now = Date.now()): string {
const deltaSeconds = Math.max(0, Math.floor((now - updatedAt) / 1000));
if (deltaSeconds < 60) return `${deltaSeconds}s`;
const minutes = Math.floor(deltaSeconds / 60);
if (minutes < 60) return `${minutes}m`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h`;
const days = Math.floor(hours / 24);
return `${days}d`;
}
export function summarizeHandoffs(rows: HandoffRecord[]): HandoffSummary {
const byStatus = emptyStatusCounts();
const byProvider: Record<string, number> = {};
for (const row of rows) {
byStatus[groupHandoffStatus(row.status)] += 1;
byProvider[row.providerId] = (byProvider[row.providerId] ?? 0) + 1;
}
return {
total: rows.length,
byStatus,
byProvider,
};
}