← Files DataARCHIVED FILE
tests/dashboard-delivery-contract.test.mjs
6.65 KB · Sep 30, 2026 · 23:19 UTC
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { test } from "node:test";
import { dataAppActionRequest } from "../templates/data-app/base/src/data-app-actions.js";
test("dashboard skill discovery treats uploaded spreadsheets as sources, not deliverables", () => {
const index = readFileSync(new URL("../skills/index/SKILL.md", import.meta.url), "utf8");
const dashboard = readFileSync(new URL("../skills/build-dashboard/SKILL.md", import.meta.url), "utf8");
const indexDescription = index.match(/^description: (.+)$/mu)?.[1];
const dashboardDescription = dashboard.match(/^description: (.+)$/mu)?.[1];
assert.ok(indexDescription, "The Data index must expose a skill description");
assert.ok(dashboardDescription, "The dashboard skill must expose a skill description");
for (const [name, description] of Object.entries({ index: indexDescription, dashboard: dashboardDescription })) {
assert.match(description, /\bdashboards?\b/iu, `${name} must recognize dashboard requests`);
assert.match(
description,
/\buploaded spreadsheets?\b/iu,
`${name} must recognize uploaded spreadsheets as dashboard sources`,
);
assert.match(description, /\bCSVs?\b/u, `${name} must recognize CSV dashboard sources`);
}
assert.match(indexDescription, /\bTSVs?\b/u, "The Data index must recognize TSV dashboard sources");
assert.match(indexDescription, /\bsource data\b/u);
assert.match(indexDescription, /without making the deliverable a spreadsheet/u);
});
test("dashboard routing locks the requested deliverable before spreadsheet companion selection", () => {
const index = readFileSync(new URL("../skills/index/SKILL.md", import.meta.url), "utf8");
const responseMode = index.match(/^## Response Mode\n([\s\S]*?)(?=^## )/mu)?.[1];
const runOrder = index.match(/^#### Run Order\n([\s\S]*?)(?=^#### Skill Selection)/mu)?.[1];
const skillSelection = index.match(/^#### Skill Selection\n([\s\S]*?)(?=^### )/mu)?.[1];
assert.ok(responseMode, "The Data index must define its response-mode policy");
assert.ok(runOrder, "The Data index must define its workflow run order");
assert.ok(skillSelection, "The Data index must define its skill-selection policy");
assert.match(responseMode, /Choose the output from the user's requested deliverable, not the source format/u);
for (const extension of [".xlsx", ".csv", ".tsv"]) {
assert.ok(
responseMode.includes(`\`${extension}\``),
`Response-mode selection must distinguish ${extension} source data from the requested output`,
);
assert.ok(
skillSelection.includes(`\`${extension}\``),
`Skill selection must keep ${extension} dashboard sources on the Data dashboard workflow`,
);
}
const lockedResponseMode = runOrder.indexOf("Choose and lock the response mode");
const dashboardPrimary = runOrder.indexOf("keeping `$build-dashboard` primary");
const companionSkillPass = runOrder.indexOf("then do one companion-skill pass");
assert.ok(lockedResponseMode >= 0, "The requested response mode must be locked");
assert.ok(
dashboardPrimary > lockedResponseMode,
"Dashboard ownership must be selected after the response mode is locked",
);
assert.ok(
companionSkillPass > dashboardPrimary,
"Spreadsheet companion skills must not be selected before dashboard ownership is locked",
);
assert.match(
skillSelection,
/load `\$build-dashboard` as the primary workflow even when its source is an uploaded spreadsheet/u,
);
assert.match(skillSelection, /Spreadsheet skills may support read-only source ingestion/u);
assert.match(
skillSelection,
/must not create or edit a workbook, own the deliverable, or redirect the output to Excel or Google Sheets unless the user explicitly requests that destination/u,
);
});
test("ordinary Publish hands the exact app and selected audience to Sites", () => {
for (const surface of ["dashboard", "report"]) {
const request = dataAppActionRequest("sites", {
surface,
accessMode: "custom",
dataAppReference: {
root: "/tmp/publish-contract",
htmlPath: "/tmp/publish-contract/dist/index.html",
},
});
assert.equal(request.title, `Publish ${surface} to Sites`);
assert.ok(request.prompt.includes("[@Sites](plugin://sites@openai-curated-remote)"));
assert.ok(request.prompt.includes("access limited to me until I invite others"));
assert.ok(request.prompt.includes("project directory: /tmp/publish-contract"));
assert.ok(request.prompt.includes("HTML file: /tmp/publish-contract/dist/index.html"));
}
});
test("Data artifact summaries choose connectors first and bound target discovery", () => {
const dashboard = readFileSync(new URL("../skills/build-dashboard/SKILL.md", import.meta.url), "utf8");
const report = readFileSync(new URL("../skills/build-report/SKILL.md", import.meta.url), "utf8");
const index = readFileSync(new URL("../skills/index/SKILL.md", import.meta.url), "utf8");
const sharing = readFileSync(new URL("../skills/share-artifact-summary/SKILL.md", import.meta.url), "utf8");
const agent = readFileSync(new URL("../skills/share-artifact-summary/agents/openai.yaml", import.meta.url), "utf8");
for (const [name, skill] of Object.entries({ dashboard, report, index })) {
const reference = skill.match(/\[\$?share-artifact-summary\]\((\.\.\/share-artifact-summary\/SKILL\.md)\)/u);
assert.ok(reference, `${name} must reference its bundled explicit-only sharing skill`);
const source = new URL(`../skills/${name === "index" ? "index" : `build-${name}`}/SKILL.md`, import.meta.url);
assert.equal(
readFileSync(new URL(reference[1], source), "utf8"),
sharing,
`${name}'s relative sharing-skill reference must resolve to the bundled workflow`,
);
}
assert.match(sharing, /up to three[^\n]*available connectors/u);
assert.match(sharing, /at most one bounded target-discovery call[^\n]*limit of 5/u);
assert.match(sharing, /published Data app's selected-view link/u);
assert.match(sharing, /keep the supported view parameters/u);
assert.match(sharing, /For other source links, remove query parameters/u);
assert.match(sharing, /Remove fragments and task IDs/u);
assert.match(sharing, /Reject URLs containing credentials[^\n]*private network addresses/u);
assert.match(sharing, /slack_complete_file_upload/u);
assert.match(agent, /allow_implicit_invocation:\s*false/u, "Artifact sharing must run only when directly invoked");
for (const surface of ["dashboard", "report"]) {
assert.match(
dataAppActionRequest("share-summary", { surface }).prompt,
/\$share-artifact-summary\b/u,
`${surface} sharing must explicitly invoke the protected sharing skill`,
);
}
});
SHA-256: 0ce7fce64a229bf790c40e2306d40176177c3c2a9c7b0e77f41d2c62a11d90c9