feat(FN-3513): add eval domain store, plugin dashboard view registry, and G

This merge adds three major features: an eval domain (`eval-store.ts`, `eval-types.ts`) with persistence schema for evaluation data; a plugin dashboard view registry with navigation integration for third-party dashboard extensions; and GitHub source metadata traceability that locks and enforces issu

Fusion-Task-Id: FN-3513
This commit is contained in:
Fusion
2026-05-05 12:20:28 -07:00
committed by gsxdsm
parent 03c0348b9e
commit 80cdb15b19
11 changed files with 125 additions and 61 deletions

View File

@@ -1185,6 +1185,10 @@ describe.skipIf(!SHOULD_RUN_EXTENSION_INTEGRATION)("fn pi extension", () => {
issueNumber: 1,
url: "https://github.com/acme/demo/issues/1",
});
expect(issueOneTask?.source?.sourceMetadata).toEqual({
issueUrl: "https://github.com/acme/demo/issues/1",
issueNumber: 1,
});
});
it("fn_task_browse_github_issues lists issues via gh api", async () => {

View File

@@ -170,7 +170,7 @@ describe("runTaskShow", () => {
[{ sourceType: "task_refine", sourceParentTaskId: "FN-2904" }, "Source: Refinement of FN-2904"],
[{ sourceType: "task_duplicate", sourceParentTaskId: "FN-2905" }, "Source: Duplicate of FN-2905"],
[
{ sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/42" } },
{ sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/42", issueNumber: 42 } },
"Source: GitHub Import (https://github.com/owner/repo/issues/42)",
],
[
@@ -1115,7 +1115,7 @@ describe("runTaskImportGitHubInteractive", () => {
issueNumber: 1,
url: "https://github.com/owner/repo/issues/1",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1", issueNumber: 1 } },
});
expect(mockCreateTask).toHaveBeenCalledWith({
title: "Third Issue",
@@ -1129,7 +1129,7 @@ describe("runTaskImportGitHubInteractive", () => {
issueNumber: 3,
url: "https://github.com/owner/repo/issues/3",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/3" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/3", issueNumber: 3 } },
});
});
@@ -1187,7 +1187,7 @@ describe("runTaskImportGitHubInteractive", () => {
issueNumber: 2,
url: "https://github.com/owner/repo/issues/2",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/2" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/2", issueNumber: 2 } },
});
const skipLine = logSpy.mock.calls.find(
@@ -1441,7 +1441,7 @@ describe("runTaskImportFromGitHub", () => {
issueNumber: 1,
url: "https://github.com/owner/repo/issues/1",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1", issueNumber: 1 } },
});
const successLine = logSpy.mock.calls.find(
@@ -1524,7 +1524,7 @@ describe("runTaskImportFromGitHub", () => {
issueNumber: 1,
url: "https://github.com/owner/repo/issues/1",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1", issueNumber: 1 } },
});
});
@@ -1546,7 +1546,7 @@ describe("runTaskImportFromGitHub", () => {
issueNumber: 1,
url: "https://github.com/owner/repo/issues/1",
},
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1" } },
source: { sourceType: "github_import", sourceMetadata: { issueUrl: "https://github.com/owner/repo/issues/1", issueNumber: 1 } },
});
});
});

View File

@@ -984,21 +984,16 @@ export async function runTaskImportGitHubInteractive(
const description = `${body}\n\nSource: ${issue.html_url}`;
// Create the task
const source = buildGitHubIssueSource(owner, repo, issue);
const task = await store.createTask({
title: title || undefined,
description,
column: "triage",
dependencies: [],
sourceIssue: {
provider: "github",
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceIssue: source.sourceIssue,
source: {
sourceType: "github_import",
sourceMetadata: { issueUrl: issue.html_url },
sourceMetadata: source.sourceMetadata,
},
});
@@ -1067,6 +1062,19 @@ export interface TaskImportOptions {
labels?: string[];
}
function buildGitHubIssueSource(owner: string, repo: string, issue: { number: number; html_url: string }) {
return {
sourceIssue: {
provider: "github" as const,
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceMetadata: { issueUrl: issue.html_url, issueNumber: issue.number },
};
}
export async function runTaskImportFromGitHub(
ownerRepo: string,
options: TaskImportOptions = {},
@@ -1131,21 +1139,16 @@ export async function runTaskImportFromGitHub(
const description = `${body}\n\nSource: ${issue.html_url}`;
// Create the task
const source = buildGitHubIssueSource(owner, repo, issue);
const task = await store.createTask({
title: title || undefined,
description,
column: "triage",
dependencies: [],
sourceIssue: {
provider: "github",
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceIssue: source.sourceIssue,
source: {
sourceType: "github_import",
sourceMetadata: { issueUrl: issue.html_url },
sourceMetadata: source.sourceMetadata,
},
});

View File

@@ -251,6 +251,19 @@ async function fetchGitHubIssuesViaGh(
}
}
function buildGitHubIssueSource(owner: string, repo: string, issue: { number: number; html_url: string }) {
return {
sourceIssue: {
provider: "github" as const,
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceMetadata: { issueUrl: issue.html_url, issueNumber: issue.number },
};
}
async function fetchGitHubIssueViaGh(
owner: string,
repo: string,
@@ -988,21 +1001,16 @@ export default function kbExtension(pi: ExtensionAPI) {
const body = issue.body?.trim() || "(no description)";
const description = `${body}\n\nSource: ${sourceUrl}`;
const source = buildGitHubIssueSource(owner, repo, issue);
const task = await store.createTask({
title: title || undefined,
description,
column: "triage",
dependencies: [],
sourceIssue: {
provider: "github",
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceIssue: source.sourceIssue,
source: {
sourceType: "github_import",
sourceMetadata: { issueUrl: issue.html_url },
sourceMetadata: source.sourceMetadata,
},
});
@@ -1085,21 +1093,16 @@ export default function kbExtension(pi: ExtensionAPI) {
const body = issue.body?.trim() || "(no description)";
const description = `${body}\n\nSource: ${sourceUrl}`;
const source = buildGitHubIssueSource(owner, repo, issue);
const task = await store.createTask({
title: title || undefined,
description,
column: "triage",
dependencies: [],
sourceIssue: {
provider: "github",
repository: `${owner}/${repo}`,
externalIssueId: String(issue.number),
issueNumber: issue.number,
url: issue.html_url,
},
sourceIssue: source.sourceIssue,
source: {
sourceType: "github_import",
sourceMetadata: { issueUrl: issue.html_url },
sourceMetadata: source.sourceMetadata,
},
});