Primeiro Commit v0.beta1

This commit is contained in:
2026-04-29 00:27:50 -03:00
parent 93d4906fb5
commit 8662a153fe
27 changed files with 16303 additions and 0 deletions

30
tests/README.md Normal file
View File

@@ -0,0 +1,30 @@
# Knowledge One View CLI Tests
This folder keeps the skill tests intentionally small and executable.
The suite covers only two themes:
1. `functions.test.mjs` checks local functions and output contracts.
2. `sales-prompts.test.mjs` checks whether common sales prompts map to quick, documented CLI commands for Oracle DV.
The tests read `SKILL.md` and `references/*.md` as the source of truth. They should not keep a parallel copy of long parameter lists, aliases, defaults, or week mappings.
Run offline tests:
```sh
node tests/run.mjs
```
Run live backend checks:
```sh
KNOWLEDGE_ONE_VIEW_LIVE=1 \
ORACLE_SI_RUNTIME_HOME=/path/to/workspace/knowledge-one-view-cli/runtime \
node tests/run.mjs
```
Offline mode does not call Oracle DV. Live mode starts with a no-cache session-context read, then runs prompt-sized backend checks. Prompts that should be org-wide commercial reads assert the primary source from `references/api-map.md`, reject fallback to `DV - SE Team`, and use larger live limits when row volume is part of the expected behavior.
Every test invocation of `fetch-sales-intelligence.mjs` is forced through `--no-cache`.
When `ORACLE_SI_RUNTIME_HOME` is set, the tests copy `auth-state.json` and `session-meta.json` into a temporary runtime first, so live checks do not rewrite the source runtime. Set `ORACLE_SI_TEST_RUNTIME_HOME` when you intentionally want to provide a writable test runtime.

597
tests/functions.test.mjs Normal file
View File

@@ -0,0 +1,597 @@
import test, { after } from "node:test";
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";
import {
catalogSaysApiMetricsAreRawRows,
catalogSaysCurrentWorkloadDefaults,
catalogSaysPreserveMixedRows,
catalogSaysUseRevenueLineCloseDate,
parseDefaultWeekYear,
parseCurrentWorkloadDefaults,
parsePrimaryCommercialSubjectArea,
parseSaAttachAliases,
parseSaAttachDateWindowField,
parseSaAttachDefaults,
parseWeekRow,
readSkillCatalogs,
} from "./helpers/catalogs.mjs";
import { skillHome } from "./helpers/cli.mjs";
const catalogs = await readSkillCatalogs();
const fetchModule = await import(
pathToFileURL(path.join(skillHome, "scripts", "fetch-sales-intelligence.mjs")).href
);
const functionTestRows = [];
function functionTest(id, title, details, fn) {
test(title, async () => {
const row = {
id,
teste: title,
entrada: details.entrada,
saida: details.saida || "",
avaliacao: "PASS",
};
try {
const output = await fn();
if (output) row.saida = output;
} catch (error) {
row.avaliacao = `FAIL; ${error.message}`;
throw error;
} finally {
functionTestRows.push(row);
}
});
}
after((t) => {
t.diagnostic(formatFunctionResultsTable(functionTestRows));
});
functionTest(
"auth-refresh-json-stdout",
"automatic auth refresh notice is emitted on stderr",
{
entrada: "source scan for the automatic refresh notice in fetch-sales-intelligence.mjs",
},
async () => {
const source = await fs.readFile(
path.join(skillHome, "scripts", "fetch-sales-intelligence.mjs"),
"utf8"
);
const notice = "Oracle DV session is missing or expired. Opening browser login to refresh auth...";
assert.match(source, new RegExp(`console\\.error\\(${JSON.stringify(notice)}\\)`));
assert.doesNotMatch(source, new RegExp(`console\\.log\\(${JSON.stringify(notice)}\\)`));
const originalLog = console.log;
const originalError = console.error;
const stdoutMessages = [];
const stderrMessages = [];
console.log = (...args) => stdoutMessages.push(args.join(" "));
console.error = (...args) => stderrMessages.push(args.join(" "));
try {
await fetchModule.withConsoleLogRoutedToStderr(async () => {
console.log("helper progress");
});
} finally {
console.log = originalLog;
console.error = originalError;
}
assert.deepEqual(stdoutMessages, []);
assert.deepEqual(stderrMessages, ["helper progress"]);
return "auto-refresh notice and imported helper progress use stderr, preserving JSON-only stdout";
}
);
functionTest(
"date-window",
"date-window functions follow documented shortcuts and week catalog",
{
entrada: "resolveDateWindow com --date, --month, --quarter, --week e combinação inválida",
},
() => {
const exact = fetchModule.resolveDateWindow({ date: "2026-05-02" });
assert.equal(exact.preset, "single-date");
assert.equal(exact.fromDate, "2026-05-02");
assert.equal(exact.toDate, "2026-05-02");
const leapDay = fetchModule.resolveDateWindow({ date: "2024-02-29" });
assert.equal(leapDay.fromDate, "2024-02-29");
assert.equal(leapDay.toDate, "2024-02-29");
assert.throws(
() => fetchModule.resolveDateWindow({ date: "2026-99-99" }),
/Invalid calendar date "2026-99-99"/
);
assert.throws(
() => fetchModule.resolveDateWindow({ date: "2026-02-29" }),
/Invalid calendar date "2026-02-29"/
);
const apiaCheck = spawnSync(
process.execPath,
[
"--input-type=module",
"-e",
`
const fetchModule = await import(${JSON.stringify(pathToFileURL(path.join(skillHome, "scripts", "fetch-sales-intelligence.mjs")).href)});
const window = fetchModule.resolveDateWindow({ date: "2011-12-30" });
console.log(window.fromDate);
`,
],
{
env: { ...process.env, TZ: "Pacific/Apia" },
encoding: "utf8",
}
);
assert.equal(apiaCheck.status, 0, apiaCheck.stderr);
assert.equal(apiaCheck.stdout.trim(), "2011-12-30");
const month = fetchModule.resolveDateWindow({ month: "2026-04" });
assert.equal(month.preset, "calendar-month");
assert.equal(month.fromDate, "2026-04-01");
assert.equal(month.toDate, "2026-04-30");
const quarter = fetchModule.resolveDateWindow({ quarter: "FY26-Q4" });
assert.equal(quarter.preset, "fiscal-quarter");
assert.equal(quarter.fiscalYear, "FY26");
assert.equal(quarter.fiscalQuarter, "Q4");
assert.equal(quarter.fromDate, "2026-03-01");
assert.equal(quarter.toDate, "2026-05-31");
const weekYear = parseDefaultWeekYear(catalogs.scriptCatalog);
const expectedWeek = parseWeekRow(catalogs.scriptCatalog, "W43");
const week = fetchModule.resolveDateWindow({
week: expectedWeek.weekLabel.toLowerCase(),
"week-year": String(weekYear),
});
assert.equal(week.weekLabel, expectedWeek.weekLabel);
assert.equal(week.fromDate, expectedWeek.fromDate);
assert.equal(week.toDate, expectedWeek.toDate);
assert.throws(
() => fetchModule.resolveDateWindow({ date: "2026-05-02", month: "2026-05" }),
/Use either --date/
);
return `single=${exact.fromDate}; month=${month.fromDate}..${month.toDate}; quarter=${quarter.fromDate}..${quarter.toDate}; week=${week.fromDate}..${week.toDate}; invalid-combo rejected`;
});
functionTest(
"sa-attach-defaults",
"SA Attach defaults and aliases come from initial-context-catalog",
{
entrada: "parseSaAttachDefaults/parseSaAttachAliases + resolveSaAttachFilters",
},
() => {
const defaults = parseSaAttachDefaults(catalogs.initialContext);
const aliases = parseSaAttachAliases(catalogs.initialContext);
const filters = fetchModule.resolveSaAttachFilters({}, {
defaultStatuses: defaults.revenueLineStatus,
});
assert.equal(filters.cluster, defaults.cluster[0]);
assert.deepEqual(filters.solutions, defaults.solution);
assert.deepEqual(filters.statuses, defaults.revenueLineStatus);
assert.deepEqual(filters.productLobs, defaults.executiveProductLob);
assert.deepEqual(filters.revenueTypeGroups, defaults.revenueTypeGroup);
assert.equal(filters.salesCreditType, defaults.salesCreditType[0]);
assert.equal(filters.minOpportunityProbability, Number(defaults.minOpportunityProbability[0]));
const lobAlias = Object.entries(aliases).find(([, values]) => values.length > 1);
const targetRevenueType = defaults.revenueTypeGroup.at(-1);
const revenueTypeAlias = Object.entries(aliases).find(([, values]) => values.includes(targetRevenueType));
assert.ok(lobAlias, "Expected at least one multi-value LOB alias in the catalog.");
assert.ok(revenueTypeAlias, "Expected a revenue-type alias for the catalog default workload group.");
const aliasFilters = fetchModule.resolveSaAttachFilters(
{
"executive-product-lob": lobAlias[0],
"revenue-type-group": revenueTypeAlias[0].split("|")[0],
},
{ defaultStatuses: defaults.revenueLineStatus }
);
assert.deepEqual(aliasFilters.productLobs, lobAlias[1]);
assert.deepEqual(aliasFilters.revenueTypeGroups, revenueTypeAlias[1]);
return `cluster=${filters.cluster}; solutions=${filters.solutions.length}; statuses=${filters.statuses.length}; aliases validated`;
});
functionTest(
"close-window-explicit-cluster",
"close-window commercial SQL honors explicit cluster without SA Attach defaults",
{
entrada: "buildPrimaryOpportunityWhereClauses com cluster Mexico",
},
() => {
const clauses = fetchModule.buildPrimaryOpportunityWhereClauses({
fromDateSql: "DATE '2026-05-01'",
toDateSql: "DATE '2026-05-31'",
statuses: ["Open"],
cluster: "Mexico",
});
const sql = clauses.join("\n");
assert.match(sql, /"Revenue Line Close Date" >= DATE '2026-05-01'/);
assert.match(sql, /"Revenue Line Close Date" <= DATE '2026-05-31'/);
assert.match(sql, /"Opportunity Status" IN \('Open'\)/);
assert.match(sql, /"Cluster" = 'Mexico'/);
assert.doesNotMatch(sql, /"Solution" IN/);
assert.doesNotMatch(sql, /"Revenue Type Group" IN/);
assert.doesNotMatch(sql, /"Sales Credit Type" =/);
const withoutCluster = fetchModule.buildPrimaryOpportunityWhereClauses({
fromDateSql: "DATE '2026-05-01'",
toDateSql: "DATE '2026-05-31'",
statuses: ["Open"],
}).join("\n");
assert.doesNotMatch(withoutCluster, /"Cluster" =/);
return "explicit cluster is applied; absent cluster preserves existing unfiltered geography behavior";
});
functionTest(
"manager-resource-workload-explicit-cluster",
"manager/resource workload SQL honors explicit cluster and defaults to Brazil",
{
entrada: "buildManagerResourceWorkloadSql com cluster Mexico e default",
},
() => {
const mexicoSql = fetchModule.buildManagerResourceWorkloadSql({
fromDateSql: "DATE '2026-05-01'",
toDateSql: "DATE '2026-05-31'",
cluster: "Mexico",
});
assert.match(mexicoSql, /"Cluster" = 'Mexico'/);
const defaultSql = fetchModule.buildManagerResourceWorkloadSql({
fromDateSql: "DATE '2026-05-01'",
toDateSql: "DATE '2026-05-31'",
});
assert.match(defaultSql, /"Cluster" = 'Brazil'/);
return "manager/resource workload cluster is explicit when provided and Brazil by default";
});
functionTest(
"coverage-limit-cap",
"coverage enrichment limit never exceeds Oracle DV maximum",
{
entrada: "resolveCoverageLimit com limites baixo, normal e alto",
},
() => {
assert.equal(fetchModule.resolveCoverageLimit(10), 5000);
assert.equal(fetchModule.resolveCoverageLimit(1000), 8000);
assert.equal(fetchModule.resolveCoverageLimit(5000), 10000);
assert.equal(fetchModule.resolveCoverageLimit(10000), 10000);
return "coverage limit is bounded to 5,000..10,000";
});
functionTest(
"current-workload-defaults",
"current workload defaults are documented and applied locally",
{
entrada: "applyCurrentWorkloadIntentDefaults para owner atual e month explícito",
},
() => {
assert.equal(catalogSaysCurrentWorkloadDefaults(catalogs, "workloads-by-owner-current"), true);
assert.equal(catalogSaysCurrentWorkloadDefaults(catalogs, "workloads-by-owner-manager-current"), true);
const expectedDefaults = parseCurrentWorkloadDefaults(catalogs, "workloads-by-owner-current");
const defaults = fetchModule.applyCurrentWorkloadIntentDefaults({
intent: "workloads-by-owner-current",
"owner-email": "territory.owner@oracle.com",
});
assert.equal(defaults.quarter, expectedDefaults.quarter);
assert.equal(defaults.solution, expectedDefaults.solution);
assert.equal(defaults["revenue-type-group"], expectedDefaults.revenueTypeGroup);
assert.equal(fetchModule.hasAnyDateWindowArgs(defaults), true);
const explicitMonth = fetchModule.applyCurrentWorkloadIntentDefaults({
month: "2026-04",
"owner-email": "territory.owner@oracle.com",
});
assert.equal(explicitMonth.month, "2026-04");
assert.equal(explicitMonth.quarter, undefined);
assert.equal(explicitMonth.solution, expectedDefaults.solution);
return `quarter=${defaults.quarter}; solution=${defaults.solution}; revenueTypeGroup=${defaults["revenue-type-group"]}; explicitMonth preserved`;
});
functionTest(
"sa-attach-window-sql",
"SA Attach window SQL uses the documented revenue-line close date field",
{
entrada: "buildSaAttachOpportunityWhereClauses com janela 2026-03-01..2026-05-31",
},
() => {
assert.equal(catalogSaysUseRevenueLineCloseDate(catalogs), true);
const defaults = parseSaAttachDefaults(catalogs.initialContext);
const dateField = parseSaAttachDateWindowField(catalogs);
const dataset = parsePrimaryCommercialSubjectArea(catalogs.apiMap);
const clauses = fetchModule.buildSaAttachOpportunityWhereClauses({
dataset,
fiscalYear: null,
previousFiscalYear: null,
fromDateSql: "DATE '2026-03-01'",
toDateSql: "DATE '2026-05-31'",
cluster: defaults.cluster[0],
solutions: [defaults.solution[0]],
statuses: defaults.revenueLineStatus,
productLobs: [defaults.executiveProductLob[0]],
revenueTypeGroups: [defaults.revenueTypeGroup.at(-1)],
salesCreditType: defaults.salesCreditType[0],
minOpportunityProbability: Number(defaults.minOpportunityProbability[0]),
ownerEmail: "territory.owner@oracle.com",
ownerManagerEmail: "territory.manager@oracle.com",
forecastTypes: ["Forecast"],
});
const sql = clauses.join("\n");
assert.match(sql, new RegExp(escapeRegExp(dateField)));
assert.match(sql, /DATE '2026-03-01'/);
assert.match(sql, /DATE '2026-05-31'/);
assert.match(sql, /Level 7 Territory Owner E-mail/);
assert.match(sql, /Revenue Line Forecast Type Group/);
assert.doesNotMatch(sql, /Revenue Line Close Year/);
return `field=${dateField}; SQL inclui forecast/owner e não usa Revenue Line Close Year`;
});
functionTest(
"scope-sql",
"scope-related SQL follows catalog-backed org-wide and my-team rules",
{
entrada: "renderViewSql para Presales Aux, Hours e srs-by-resource-email",
},
() => {
const coverageOrg = fetchModule.renderViewSql("sa-attach-presales-coverage");
const coverageTeam = fetchModule.renderViewSql("sa-attach-presales-coverage", { scope: "my-team" });
const hoursOrg = fetchModule.renderViewSql("sa-attach-hours-by-opportunity");
const hoursTeam = fetchModule.renderViewSql("sa-attach-hours-by-opportunity", { scope: "my-team" });
const srTeam = fetchModule.renderViewSql("srs-by-resource-email", {
resourceEmailSql: "'resource.member@oracle.com'",
matchRole: "team",
srStatuses: [],
});
const srLead = fetchModule.renderViewSql("srs-by-resource-email", {
resourceEmailSql: "'resource.member@oracle.com'",
matchRole: "lead",
srStatuses: [],
});
assert.match(catalogs.skill, /Presales Involvement Aux - V1.*org-wide/s);
assert.doesNotMatch(coverageOrg, /SEC_ARIA_SI-SR-TEAM/);
assert.match(coverageTeam, /SEC_ARIA_SI-SR-TEAM/);
assert.doesNotMatch(hoursOrg, /SEC_ARIA_SI-SR-TEAM/);
assert.match(hoursTeam, /SEC_ARIA_SI-SR-TEAM/);
assert.match(srTeam, /SE Team Level 1 Email Address/);
assert.match(srTeam, /SE Team Level 4 Email Address/);
assert.match(srLead, /"Service Request"\."Lead Email" = 'resource.member@oracle.com'/);
return "org-wide sem SEC_ARIA; my-team com SEC_ARIA; SR team usa levels 1..4; lead só quando explícito";
});
functionTest(
"current-team-summary",
"current-team coverage summaries preserve unmatched commercial rows",
{
entrada: "summarizeCurrentTeamOpportunityCoverage com 2 oportunidades e 1 cobertura",
},
() => {
assert.equal(catalogSaysPreserveMixedRows(catalogs), true);
const result = fetchModule.summarizeCurrentTeamOpportunityCoverage(
[
{
opportunityId: "OPP-1",
opportunityName: "Alpha",
customerName: "Acme",
opportunityStatus: "Open",
closeDate: "2026-03-31",
salesStage: "Develop",
bookingValue: 100000,
workloadAmount: 50000,
},
{
opportunityId: "OPP-2",
opportunityName: "Beta",
customerName: "Bravo",
opportunityStatus: "Open",
closeDate: "2026-04-01",
salesStage: "Close",
bookingValue: 200000,
workloadAmount: 75000,
},
],
[
{
opportunityId: "OPP-1",
seTeamLevel5EmailAddress: "engineer.one@oracle.com",
opportunityHoursAttribute: 6,
},
]
);
assert.equal(result.records.length, 2);
assert.equal(result.summary.totalWindowOpportunities, 2);
assert.equal(result.summary.matchedOpportunities, 1);
assert.equal(result.summary.unmatchedOpportunities, 1);
assert.equal(result.summary.totalBookingValue, 300000);
assert.equal(result.summary.totalWorkloadAmount, 125000);
const unmatched = result.records.find((record) => record.opportunityId === "OPP-2");
assert.deepEqual(unmatched.teamMemberEmails, []);
assert.equal(unmatched.coverageRows, 0);
return `records=${result.records.length}; matched=${result.summary.matchedOpportunities}; unmatched=${result.summary.unmatchedOpportunities}; totalWorkload=${result.summary.totalWorkloadAmount}`;
});
functionTest(
"manager-resource-summary",
"manager-resource workload summaries keep resource involvement details",
{
entrada: "summarizeOrgWideRevenueLineCoverage com cobertura Aux e cenário opcional com SR injetado",
},
() => {
const defaultResult = fetchModule.summarizeOrgWideRevenueLineCoverage(
[
{
closeDate: "2026-04-06",
revenueLineId: "RL-1",
opportunityId: "OPP-1",
opportunityName: "Alpha",
customerName: "Acme",
workloadAmount: 240000,
},
],
[
{
opportunityId: "OPP-1",
seTeamLevel4EmailAddress: "resource.manager.a@oracle.com",
seTeamLevel5EmailAddress: "resource.member.a@oracle.com",
},
{
opportunityId: "OPP-1",
seTeamLevel4EmailAddress: "resource.manager.b@oracle.com",
seTeamLevel5EmailAddress: "resource.member.b@oracle.com",
},
]
);
assert.deepEqual(defaultResult.records[0].resourceDetails, [
{
resourceEmail: "resource.member.a@oracle.com",
companionEmails: ["resource.member.b@oracle.com"],
},
{
resourceEmail: "resource.member.b@oracle.com",
companionEmails: ["resource.member.a@oracle.com"],
},
]);
assert.equal(Object.hasOwn(defaultResult.records[0].resourceDetails[0], "srNumbers"), false);
const result = fetchModule.summarizeOrgWideRevenueLineCoverage(
[
{
closeDate: "2026-04-06",
revenueLineId: "RL-1",
opportunityId: "OPP-1",
opportunityName: "Alpha",
customerName: "Acme",
workloadAmount: 240000,
},
{
closeDate: "2026-04-07",
revenueLineId: "RL-2",
opportunityId: "OPP-2",
opportunityName: "Beta",
customerName: "Bravo",
workloadAmount: 367000,
},
],
[
{
opportunityId: "OPP-1",
seTeamLevel4EmailAddress: "resource.manager.a@oracle.com",
seTeamLevel5EmailAddress: "resource.member.a@oracle.com",
},
{
opportunityId: "OPP-1",
seTeamLevel4EmailAddress: "resource.manager.b@oracle.com",
seTeamLevel5EmailAddress: "resource.member.b@oracle.com",
},
],
new Map([["OPP-1::resource.member.a@oracle.com", new Set(["SR-100"])] ]),
new Map([
[
"resource.member.a@oracle.com",
new Map([
["SR-900", { srNumber: "SR-900", customerName: "Acme", title: "Internal follow-up" }],
["SR-901", { srNumber: "SR-901", customerName: "Other Corp", title: "Ignore me" }],
]),
],
])
);
assert.equal(result.records.length, 1);
assert.equal(result.records[0].revenueLineId, "RL-1");
assert.deepEqual(result.records[0].managerEmails, [
"resource.manager.a@oracle.com",
"resource.manager.b@oracle.com",
]);
assert.deepEqual(result.records[0].resourceEmails, [
"resource.member.a@oracle.com",
"resource.member.b@oracle.com",
]);
const resourceA = result.records[0].resourceDetails.find(
(detail) => detail.resourceEmail === "resource.member.a@oracle.com"
);
assert.deepEqual(resourceA.srNumbers, ["SR-100", "SR-900"]);
assert.deepEqual(resourceA.directSrNumbers, ["SR-100"]);
assert.deepEqual(resourceA.candidateInternalSrNumbers, ["SR-900"]);
assert.equal(resourceA.srLinkageMode, "direct-plus-candidate-internal");
assert.deepEqual(resourceA.companionEmails, ["resource.member.b@oracle.com"]);
assert.equal(result.summary.totalWindowRevenueLines, 2);
assert.equal(result.summary.matchedRevenueLines, 1);
assert.equal(result.summary.matchedOpportunities, 1);
assert.equal(result.summary.totalWorkloadAmount, 240000);
assert.equal(result.summary.resourcesMatched, 2);
return `defaultResourceDetails=${defaultResult.records[0].resourceDetails.length}; defaultSrFields=omitted; optionalSrLinkage=${resourceA.srLinkageMode}; resourcesMatched=${result.summary.resourcesMatched}`;
});
functionTest(
"api-metrics",
"API metrics count raw backend rows and ignore local-cache-only rows",
{
entrada: "buildApiMetrics com rows 3 + 2 e cache local não contado",
},
() => {
assert.equal(catalogSaysApiMetricsAreRawRows(catalogs), true);
const metrics = fetchModule.buildApiMetrics([
{
label: "window",
result: { aResults: [[1], [2], [3]] },
},
{
label: "coverage",
result: { aResults: [[1], [2]] },
},
{
label: "sessionMetaCache",
rowsReturned: 0,
source: "session-meta-cache",
countedInTotal: false,
},
]);
assert.equal(metrics.totalRowsPulledFromApi, 5);
assert.equal(metrics.queries.length, 3);
assert.equal(metrics.explanation, "Raw rows pulled from API: 5.");
return `totalRowsPulledFromApi=${metrics.totalRowsPulledFromApi}; queries=${metrics.queries.length}; local-cache ignored`;
});
function formatFunctionResultsTable(rows) {
const header = ["id", "teste", "entrada", "saida", "avaliacao"];
const lines = [
`| ${header.join(" | ")} |`,
`| ${header.map(() => "---").join(" | ")} |`,
...rows.map((row) =>
`| ${markdownCell(row.id)} | ${markdownCell(row.teste)} | ${markdownCell(row.entrada)} | ${markdownCell(row.saida)} | ${markdownCell(row.avaliacao)} |`
),
];
return lines.join("\n");
}
function markdownCell(value) {
return String(value ?? "")
.replace(/\r?\n/g, "<br>")
.replace(/\|/g, "\\|");
}
function escapeRegExp(value) {
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

190
tests/helpers/catalogs.mjs Normal file
View File

@@ -0,0 +1,190 @@
import fs from "node:fs/promises";
import path from "node:path";
import { skillHome } from "./cli.mjs";
export async function readSkillCatalogs() {
const [skill, scriptCatalog, initialContext, apiMap] = await Promise.all([
fs.readFile(path.join(skillHome, "SKILL.md"), "utf8"),
fs.readFile(path.join(skillHome, "references", "script-catalog.md"), "utf8"),
fs.readFile(path.join(skillHome, "references", "initial-context-catalog.md"), "utf8"),
fs.readFile(path.join(skillHome, "references", "api-map.md"), "utf8"),
]);
return {
skill,
scriptCatalog,
initialContext,
apiMap,
allText: [skill, scriptCatalog, initialContext, apiMap].join("\n"),
};
}
export function documentedFlags(catalogs) {
const flags = new Set();
const regex = /`(--[a-z0-9-]+)(?:\s+[^`]*)?`/gi;
let match = regex.exec(catalogs.allText);
while (match) {
flags.add(match[1]);
match = regex.exec(catalogs.allText);
}
return flags;
}
export function catalogMentionsIntent(catalogs, intentName) {
return new RegExp(`\\b${escapeRegExp(intentName)}\\b`).test(catalogs.skill + "\n" + catalogs.scriptCatalog);
}
export function catalogMentionsView(catalogs, viewName) {
return new RegExp(`\\b${escapeRegExp(viewName)}\\b`).test(catalogs.skill + "\n" + catalogs.scriptCatalog);
}
export function commandAppearsInCatalog(catalogs, args) {
const normalizedCatalog = normalizeWhitespace(catalogs.skill + "\n" + catalogs.scriptCatalog + "\n" + catalogs.apiMap);
const normalizedArgs = normalizeWhitespace(args.join(" "));
return normalizedCatalog.includes(normalizedArgs);
}
export function parseDefaultWeekYear(scriptCatalog) {
const match = /-\s*`week-year\s+(\d{4})`/i.exec(scriptCatalog);
if (!match) {
throw new Error("Could not parse default week-year from references/script-catalog.md.");
}
return Number(match[1]);
}
export function parseWeekRow(scriptCatalog, weekLabel) {
const normalizedLabel = String(weekLabel).toUpperCase().replace(/^W?/, "W");
const regex = new RegExp(`\\|\\s*${escapeRegExp(normalizedLabel)}\\s*\\|\\s*(\\d{4}-\\d{2}-\\d{2})\\s*\\|\\s*(\\d{4}-\\d{2}-\\d{2})\\s*\\|`, "i");
const match = regex.exec(scriptCatalog);
if (!match) {
throw new Error(`Could not parse ${normalizedLabel} from references/script-catalog.md.`);
}
return {
weekLabel: normalizedLabel,
fromDate: match[1],
toDate: match[2],
};
}
export function parseSaAttachDefaults(initialContext) {
const line = findLine(initialContext, "SA Attach defaults:");
const rawDefaults = line.slice(line.indexOf(":") + 1).split(";").map((part) => part.trim()).filter(Boolean);
const defaults = {};
for (const part of rawDefaults) {
const match = /`--([^=]+)=([^`]+)`/.exec(part);
if (!match) continue;
defaults[toCamelKey(match[1])] = splitCatalogCsv(match[2]);
}
return defaults;
}
export function parseSaAttachAliases(initialContext) {
const line = findLine(initialContext, "SA Attach aliases:");
const aliases = {};
const rawAliases = line.slice(line.indexOf(":") + 1).split(";").map((part) => part.trim()).filter(Boolean);
for (const item of rawAliases) {
const match = /`([^`]+)`\s*->\s*`([^`]+)`/.exec(item);
if (!match) continue;
aliases[match[1].toLowerCase()] = splitCatalogCsv(match[2]);
}
return aliases;
}
export function catalogSaysCurrentWorkloadDefaults(catalogs, intentName) {
try {
parseCurrentWorkloadDefaults(catalogs, intentName);
return true;
} catch {
return false;
}
}
export function parseCurrentWorkloadDefaults(catalogs, intentName) {
const source = catalogs.skill + "\n" + catalogs.scriptCatalog;
const pattern = new RegExp(
`\\\`${escapeRegExp(intentName)}\\\`[\\s\\S]{0,500}?defaults? to \\\`([^\\\`]+)\\\`, \\\`([^\\\`]+)\\\`, and \\\`([^\\\`]+)\\\``,
"i"
);
const match = pattern.exec(source);
if (!match) {
throw new Error(`Could not parse documented defaults for ${intentName}.`);
}
return {
quarter: match[1],
solution: match[2],
revenueTypeGroup: match[3],
};
}
export function catalogSaysUseRevenueLineCloseDate(catalogs) {
try {
parseSaAttachDateWindowField(catalogs);
return true;
} catch {
return false;
}
}
export function parseSaAttachDateWindowField(catalogs) {
const match =
/date-window flags now constrain `([^`]+)` directly/i.exec(catalogs.skill) ||
/date-window flags are applied to `([^`]+)`/i.exec(catalogs.scriptCatalog);
if (!match) {
throw new Error("Could not parse the SA Attach date-window field from references.");
}
return match[1];
}
export function parsePrimaryCommercialSubjectArea(apiMap) {
const match = /Primary commercial subject area:[\s\S]*?`([^`]+)`/i.exec(apiMap);
if (!match) {
throw new Error("Could not parse the primary commercial subject area from references/api-map.md.");
}
return match[1];
}
export function parsePrimaryCommercialSourceName(apiMap) {
const subjectArea = parsePrimaryCommercialSubjectArea(apiMap);
const match = /\.'([^']+)'\)$/i.exec(subjectArea);
if (!match) {
throw new Error("Could not parse the primary commercial source name from references/api-map.md.");
}
return match[1];
}
export function catalogSaysPreserveMixedRows(catalogs) {
return /preserve every org-wide opportunity\/workload row/i.test(catalogs.skill);
}
export function catalogSaysApiMetricsAreRawRows(catalogs) {
return /apiMetrics\.totalRowsPulledFromApi/i.test(catalogs.skill)
&& /Do not add local-cache-only rows/i.test(catalogs.skill);
}
export function splitCatalogCsv(value) {
return String(value || "")
.split(",")
.map((item) => item.trim())
.filter(Boolean);
}
function findLine(text, marker) {
const line = String(text)
.split(/\r?\n/)
.find((candidate) => candidate.includes(marker));
if (!line) {
throw new Error(`Could not find "${marker}" in catalog text.`);
}
return line;
}
function toCamelKey(flagName) {
return flagName.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
}
function normalizeWhitespace(value) {
return String(value).replace(/\s+/g, " ").trim();
}
function escapeRegExp(value) {
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

168
tests/helpers/cli.mjs Normal file
View File

@@ -0,0 +1,168 @@
import { spawn } from "node:child_process";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
const helperDir = path.dirname(fileURLToPath(import.meta.url));
export const testsDir = path.resolve(helperDir, "..");
export const skillHome = path.resolve(testsDir, "..");
export const fetchScriptPath = path.join(skillHome, "scripts", "fetch-sales-intelligence.mjs");
let preparedRuntimeHomePromise = null;
export function testRuntimeHome() {
return (
process.env.ORACLE_SI_TEST_RUNTIME_HOME ||
path.join(os.tmpdir(), "knowledge-one-view-cli-tests", "runtime")
);
}
async function prepareRuntimeHome() {
if (process.env.ORACLE_SI_TEST_RUNTIME_HOME) {
await fs.mkdir(process.env.ORACLE_SI_TEST_RUNTIME_HOME, { recursive: true });
return process.env.ORACLE_SI_TEST_RUNTIME_HOME;
}
const runtimeHome = testRuntimeHome();
if (!process.env.ORACLE_SI_RUNTIME_HOME) {
await fs.mkdir(runtimeHome, { recursive: true });
return runtimeHome;
}
if (!preparedRuntimeHomePromise) {
preparedRuntimeHomePromise = (async () => {
await fs.rm(runtimeHome, { recursive: true, force: true });
await fs.mkdir(runtimeHome, { recursive: true });
for (const fileName of ["auth-state.json", "session-meta.json"]) {
await fs.copyFile(
path.join(process.env.ORACLE_SI_RUNTIME_HOME, fileName),
path.join(runtimeHome, fileName)
);
}
return runtimeHome;
})();
}
return preparedRuntimeHomePromise;
}
export function flagsInArgs(args) {
return args.filter((arg) => String(arg).startsWith("--"));
}
export function argValue(args, flagName) {
const index = args.indexOf(flagName);
return index >= 0 ? args[index + 1] : null;
}
export function executionModes(args) {
return ["--intent", "--view", "--query", "--sql"].filter((flagName) => args.includes(flagName));
}
export function withoutFlags(args, flagsToRemove) {
const flags = new Set(flagsToRemove);
const next = [];
for (let index = 0; index < args.length; index += 1) {
const token = args[index];
if (!flags.has(token)) {
next.push(token);
continue;
}
if (token !== "--query" && token !== "--render-sql" && args[index + 1] && !args[index + 1].startsWith("--")) {
index += 1;
}
}
return next;
}
export async function runFetch(cliArgs, options = {}) {
const {
expectCode = 0,
timeoutMs = 120000,
runtimeHome: requestedRuntimeHome = null,
} = options;
const runtimeHome = requestedRuntimeHome || (await prepareRuntimeHome());
const noCacheArgs = cliArgs.includes("--no-cache") ? [...cliArgs] : [...cliArgs, "--no-cache"];
const finalArgs = noCacheArgs.includes("--runtime-home")
? noCacheArgs
: [...noCacheArgs, "--runtime-home", runtimeHome];
return new Promise((resolve, reject) => {
const child = spawn(process.execPath, [fetchScriptPath, ...finalArgs], {
stdio: ["ignore", "pipe", "pipe"],
env: process.env,
});
let stdout = "";
let stderr = "";
let timedOut = false;
const startedAt = process.hrtime.bigint();
const timer = setTimeout(() => {
timedOut = true;
child.kill();
}, timeoutMs);
child.stdout.setEncoding("utf8");
child.stderr.setEncoding("utf8");
child.stdout.on("data", (chunk) => {
stdout += chunk;
});
child.stderr.on("data", (chunk) => {
stderr += chunk;
});
child.on("error", reject);
child.on("close", (code) => {
clearTimeout(timer);
const durationMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000;
let json = null;
try {
json = stdout.trim() ? JSON.parse(stdout) : null;
} catch {}
const result = {
args: finalArgs,
code,
stdout,
stderr,
json,
timedOut,
durationMs,
};
if (expectCode !== null && code !== expectCode) {
reject(
new Error(
[
`Unexpected exit code ${code}; expected ${expectCode}.`,
`Command: ${process.execPath} ${fetchScriptPath} ${finalArgs.join(" ")}`,
stderr.trim() || stdout.trim(),
]
.filter(Boolean)
.join("\n")
)
);
return;
}
if (expectCode === 0 && (!json || typeof json !== "object")) {
reject(
new Error(
[
"Expected JSON output from fetch-sales-intelligence.mjs.",
`Command: ${process.execPath} ${fetchScriptPath} ${finalArgs.join(" ")}`,
stderr.trim() || stdout.trim(),
]
.filter(Boolean)
.join("\n")
)
);
return;
}
resolve(result);
});
});
}

142
tests/helpers/examples.mjs Normal file
View File

@@ -0,0 +1,142 @@
import { runFetch } from "./cli.mjs";
const EMAIL_REGEX = /^[a-z0-9._%+-]+@oracle\.com$/i;
const PLACEHOLDER_REGEX = /\{\{([a-zA-Z0-9]+)\}\}/g;
export function hasPlaceholders(value) {
return PLACEHOLDER_REGEX.test(String(value || ""));
}
export function resolvePlaceholders(value, examples = {}, { allowUnresolved = false } = {}) {
return String(value).replace(PLACEHOLDER_REGEX, (match, key) => {
if (examples[key]) return examples[key];
if (allowUnresolved) return match;
throw new Error(`Missing live example value for {{${key}}}.`);
});
}
export function resolvePromptCase(item, examples = {}, { allowUnresolved = false } = {}) {
return {
...item,
prompt: resolvePlaceholders(item.prompt, examples, { allowUnresolved }),
args: item.args.map((arg) => resolvePlaceholders(arg, examples, { allowUnresolved })),
...(item.liveArgs
? { liveArgs: item.liveArgs.map((arg) => resolvePlaceholders(arg, examples, { allowUnresolved })) }
: {}),
};
}
export async function buildLiveExampleContext(catalogs) {
const catalogResourceManagers = emailsFromCatalog(catalogs.initialContext);
const [pipelineSample, presalesSample] = await Promise.all([
runFetch(["--view", "sa-attach-pipeline-details", "--limit", "500"], { timeoutMs: 180000 }),
runFetch(["--view", "sa-attach-presales-coverage", "--limit", "500"], { timeoutMs: 180000 }),
]);
const pipelineRecords = pipelineSample.json.records || [];
const presalesRecords = presalesSample.json.records || [];
const resourceManagerEmails = uniqueEmails([
...catalogResourceManagers,
...valuesFromRecords(presalesRecords, ["seTeamLevel4EmailAddress"]),
]);
const resourceMemberEmails = uniqueEmails(valuesFromRecords(presalesRecords, ["seTeamLevel5EmailAddress"]));
const territoryOwnerEmails = uniqueEmails(
valuesFromRecords(pipelineRecords, ["level7TerritoryOwnerEmail", "territoryOwnerEmail"])
);
const territoryManagerEmails = uniqueEmails(
valuesFromRecords(pipelineRecords, [
"level2TerritoryOwnerEmail",
"level3TerritoryOwnerEmail",
"level4TerritoryOwnerEmail",
"level5TerritoryOwnerEmail",
"level6TerritoryOwnerEmail",
])
);
const [resourceManagerEmailA, resourceManagerEmailB] = pickDistinct(
resourceManagerEmails,
2,
"resource manager emails"
);
return {
examples: {
resourceManagerEmail: pickRandom(resourceManagerEmails, "resource manager email"),
resourceManagerEmailA,
resourceManagerEmailB,
resourceManagerEmailList: `${resourceManagerEmailA},${resourceManagerEmailB}`,
territoryOwnerEmail: pickRandom(territoryOwnerEmails, "territory owner email"),
territoryManagerEmail: pickRandom(territoryManagerEmails, "territory manager email"),
resourceMember: pickRandom(resourceMemberEmails, "resource member email"),
},
trace: [
{
script: "fetch-sales-intelligence.mjs",
args: pipelineSample.args,
result: `ok; records=${pipelineRecords.length}; source=${pipelineSample.json.request?.dataSource || "unknown"}`,
profiles: ["territoryOwnerEmail", "territoryManagerEmail"],
},
{
script: "fetch-sales-intelligence.mjs",
args: presalesSample.args,
result: `ok; records=${presalesRecords.length}; source=${presalesSample.json.request?.dataSource || "unknown"}`,
profiles: ["resourceManagerEmail", "resourceManagerEmailA", "resourceManagerEmailB", "resourceMember"],
},
],
poolSizes: {
resourceManagerEmails: resourceManagerEmails.length,
resourceMemberEmails: resourceMemberEmails.length,
territoryOwnerEmails: territoryOwnerEmails.length,
territoryManagerEmails: territoryManagerEmails.length,
},
};
}
export function placeholderKeysForItem(item) {
const text = [item.prompt, ...(item.args || []), ...(item.liveArgs || [])].join("\n");
return Array.from(text.matchAll(PLACEHOLDER_REGEX), (match) => match[1]);
}
function emailsFromCatalog(text) {
return uniqueEmails(Array.from(String(text || "").matchAll(/[a-z0-9._%+-]+@oracle\.com/gi), (match) => match[0]));
}
function valuesFromRecords(records, fieldNames) {
const values = [];
for (const record of records || []) {
for (const fieldName of fieldNames) {
if (record?.[fieldName]) values.push(record[fieldName]);
}
}
return values;
}
function uniqueEmails(values) {
return Array.from(
new Set(
values
.map((value) => String(value || "").trim().toLowerCase())
.filter((value) => EMAIL_REGEX.test(value))
.filter((value) => !/^(resource|territory)\./.test(value))
)
).sort();
}
function pickRandom(values, label) {
if (!values.length) {
throw new Error(`Could not resolve any real ${label} from the skill catalogs or live DV sample.`);
}
return values[Math.floor(Math.random() * values.length)];
}
function pickDistinct(values, count, label) {
if (values.length < count) {
throw new Error(`Could not resolve ${count} distinct real ${label} from the skill catalogs or live DV sample.`);
}
const remaining = [...values];
const picked = [];
while (picked.length < count) {
const index = Math.floor(Math.random() * remaining.length);
picked.push(remaining.splice(index, 1)[0]);
}
return picked;
}

View File

@@ -0,0 +1,163 @@
import test from "node:test";
import assert from "node:assert/strict";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { skillHome } from "./helpers/cli.mjs";
const cliShared = await import(pathToFileURL(path.join(skillHome, "scripts", "lib", "cli-shared.mjs")).href);
const outputContract = await import(pathToFileURL(path.join(skillHome, "scripts", "lib", "output-contract.mjs")).href);
const runtimePaths = await import(pathToFileURL(path.join(skillHome, "scripts", "lib", "runtime-paths.mjs")).href);
const authShared = await import(pathToFileURL(path.join(skillHome, "scripts", "lib", "auth-shared.mjs")).href);
test("cli-shared parses flags and csv values for agent-built commands", () => {
assert.deepEqual(
cliShared.parseArgs([
"ignored-position",
"--query",
"--select",
"opportunityId,",
"customerName",
"--render-sql",
"--limit",
"10",
]),
{
query: "true",
select: "opportunityId, customerName",
"render-sql": "true",
limit: "10",
}
);
const fallback = ["default"];
assert.equal(cliShared.splitCsv("", fallback), fallback);
assert.deepEqual(cliShared.splitCsv(" opportunityId, , customerName , bookingValue "), [
"opportunityId",
"customerName",
"bookingValue",
]);
});
test("output-contract formats display money while preserving API metrics defaults", () => {
const payload = outputContract.preparePayloadForOutput({
columns: ["opportunityId", "bookingValue", "workloadAmount"],
request: {
query: {
measure: [{ fieldName: "bookingValue", outputName: "totalBooking" }],
},
},
records: [
{
opportunityId: "OPP-1",
bookingValue: 1234567,
workloadAmount: "90,000",
totalBooking: 5000,
note: "unchanged",
},
],
summary: {
totalBookingValue: 1234567,
nested: { workloadAmount: 23000 },
},
});
assert.equal(payload.records[0].bookingValue, "1.234k");
assert.equal(payload.records[0].workloadAmount, "90k");
assert.equal(payload.records[0].totalBooking, "5k");
assert.equal(payload.records[0].note, "unchanged");
assert.equal(payload.summary.totalBookingValue, "1.234k");
assert.equal(payload.summary.nested.workloadAmount, "23k");
assert.equal(payload.apiMetrics.totalRowsPulledFromApi, 0);
});
test("output-contract normalizes Oracle cells and warnings", () => {
assert.equal(outputContract.normalizeCell("02-MAY-26"), "2026-05-02");
assert.equal(outputContract.normalizeCell("31-DEC-99"), "1999-12-31");
assert.equal(outputContract.normalizeCell("__CODEX_NULL__"), null);
assert.equal(outputContract.normalizeCell(undefined), null);
assert.deepEqual(
outputContract.mapRows(["closeDate", "amount"], [["02-MAY-2026", "__CODEX_NULL__"]]),
[{ closeDate: "2026-05-02", amount: null }]
);
const warnings = outputContract.buildWarnings({
requestedLimit: 10,
recordsCount: 10,
customSql: true,
customSqlColumnsResolved: false,
});
assert.equal(warnings.length, 2);
assert.match(warnings[0], /matches the requested limit/);
assert.match(warnings[1], /Custom SQL records are returned as raw row arrays/);
});
test("runtime-paths routes final and temporary outputs under the workspace skill folder", () => {
const workspaceRoot = path.join("/tmp", "kov-runtime-contracts");
const runtimeHome = path.join(workspaceRoot, "knowledge-one-view-cli", "runtime-test");
const normalizedRuntimeHome = path.join(workspaceRoot, "knowledge-one-view-cli", "runtime");
assert.equal(runtimePaths.resolveRuntimeHome(runtimeHome), normalizedRuntimeHome);
assert.equal(
runtimePaths.resolveOutputFilePath("final.json", runtimeHome),
path.join(workspaceRoot, "knowledge-one-view-cli", "output", "final.json")
);
assert.equal(
runtimePaths.resolveOutputFilePath("tmp-render.json", runtimeHome),
path.join(workspaceRoot, "knowledge-one-view-cli", "tmp", "tmp-render.json")
);
assert.equal(
runtimePaths.resolveOutputFilePath("reports/final.json", runtimeHome),
path.join(workspaceRoot, "knowledge-one-view-cli", "reports", "final.json")
);
});
test("runtime-paths refuses to infer a workspace inside .codex", () => {
assert.throws(
() => runtimePaths.resolveWorkspaceRoot(path.join(runtimePaths.CODEX_HOME, "skills", "knowledge-one-view-cli")),
/Cannot infer a workspace root/
);
});
test("auth-shared builds cookie headers with domain, path, secure, and expiry rules", () => {
const now = Math.floor(Date.now() / 1000);
const header = authShared.cookieHeaderFor("https://salesintelligence-dv.oracle.com/analytics/saw.dll", [
{ name: "root", value: "1", domain: ".oracle.com", path: "/", secure: true, expires: -1 },
{ name: "deep", value: "2", domain: "salesintelligence-dv.oracle.com", path: "/analytics", secure: true, expires: now + 60 },
{ name: "expired", value: "3", domain: "oracle.com", path: "/", secure: true, expires: now - 60 },
{ name: "httpOnly", value: "4", domain: "oracle.com", path: "/", secure: true, expires: -1 },
{ name: "wrong", value: "5", domain: "example.com", path: "/", secure: true, expires: -1 },
{ name: "insecureOnly", value: "6", domain: "oracle.com", path: "/", secure: false, expires: -1 },
]);
assert.equal(header, "deep=2; root=1; httpOnly=4; insecureOnly=6");
});
test("auth-shared splits and merges Set-Cookie headers", () => {
assert.deepEqual(
authShared.splitSetCookieHeader("a=1; Expires=Wed, 21 Oct 2030 07:28:00 GMT; Path=/, b=2; Path=/analytics; HttpOnly; SameSite=None; Secure"),
[
"a=1; Expires=Wed, 21 Oct 2030 07:28:00 GMT; Path=/",
"b=2; Path=/analytics; HttpOnly; SameSite=None; Secure",
]
);
const state = { cookies: [{ name: "a", value: "old", domain: "oracle.com", path: "/", expires: -1 }] };
const changed = authShared.mergeCookiesFromHeader(
state,
"https://salesintelligence-dv.oracle.com/analytics/saw.dll",
"a=1; Domain=.oracle.com; Path=/, b=2; Path=/analytics; HttpOnly; SameSite=None; Secure"
);
assert.equal(changed, true);
assert.equal(state.cookies.length, 2);
assert.equal(state.cookies.find((cookie) => cookie.name === "a").value, "1");
assert.equal(state.cookies.find((cookie) => cookie.name === "b").sameSite, "None");
assert.equal(state.cookies.find((cookie) => cookie.name === "b").httpOnly, true);
});
test("auth-shared classifies refresh-required errors", () => {
assert.equal(authShared.isAuthRefreshRequiredError(new Error("Request redirected to Oracle sign-in")), true);
assert.equal(authShared.isAuthRefreshRequiredError(new Error("Could not find auth state at /tmp/auth-state.json")), true);
assert.equal(authShared.isAuthRefreshRequiredError(new Error("Unsupported --limit abc")), false);
});

View File

@@ -0,0 +1,93 @@
[
{
"id": "generic-pipeline",
"prompt": "Me traga o pipeline de oportunidades no Knowledge One View.",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "opportunities-default", "--limit", "20"],
"liveArgs": ["--intent", "opportunities-default", "--limit", "1000"],
"liveExpect": {
"scopeMode": "org-wide",
"dataSource": "primaryCommercial",
"allowFallback": false,
"minRecords": 100,
"minApiRows": 100
}
},
{
"id": "exact-close-date",
"prompt": "Quais oportunidades fecham em 2026-05-02?",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "opportunities-close-date", "--date", "2026-05-02", "--limit", "10"],
"liveArgs": ["--intent", "opportunities-close-date", "--date", "2026-05-02", "--limit", "1000"],
"liveExpect": {
"scopeMode": "org-wide",
"dataSource": "primaryCommercial",
"allowFallback": false,
"minRecords": 1,
"minApiRows": 1
}
},
{
"id": "calendar-month",
"prompt": "Quais oportunidades fecham em abril de 2026?",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "opportunities-close-month", "--month", "2026-04", "--limit", "10"],
"liveArgs": ["--intent", "opportunities-close-month", "--month", "2026-04", "--limit", "1000"],
"liveExpect": {
"scopeMode": "org-wide",
"dataSource": "primaryCommercial",
"allowFallback": false,
"minRecords": 11,
"minApiRows": 11
}
},
{
"id": "manager-week",
"prompt": "Quais oportunidades do manager {{resourceManagerEmail}} fecham na week 43?",
"catalogRefs": ["SKILL.md", "references/initial-context-catalog.md", "references/script-catalog.md#week-reference"],
"args": ["--intent", "opportunities-by-manager-close-window", "--manager-email", "{{resourceManagerEmail}}", "--week", "w43", "--week-year", "catalog-default", "--limit", "10"]
},
{
"id": "owner-workload-current",
"prompt": "Me mostre os workloads em forecast agora do vendedor {{territoryOwnerEmail}}.",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "workloads-by-owner-current", "--owner-email", "{{territoryOwnerEmail}}", "--forecast-type", "Forecast", "--limit", "10"]
},
{
"id": "owner-manager-workload-current",
"prompt": "Quais workloads em forecast agora dos owners abaixo de {{territoryManagerEmail}}?",
"catalogRefs": ["SKILL.md", "references/initial-context-catalog.md"],
"args": ["--intent", "workloads-by-owner-manager-current", "--owner-manager-email", "{{territoryManagerEmail}}", "--forecast-type", "Forecast", "--limit", "10"]
},
{
"id": "manager-resource-next-7-days",
"prompt": "Workloads com close date nos proximos 7 dias em oportunidades com recursos abaixo de {{resourceManagerEmailA}} e {{resourceManagerEmailB}}.",
"catalogRefs": ["SKILL.md", "references/initial-context-catalog.md"],
"args": ["--intent", "workloads-by-manager-resource-close-window", "--manager-email-list", "{{resourceManagerEmailList}}", "--from-date", "today", "--to-date", "+7d", "--limit", "10"],
"liveExpect": {
"scopeMode": "org-wide",
"dataSource": "primaryCommercial",
"allowFallback": false,
"noDvSeTeamQueries": true
}
},
{
"id": "resource-srs",
"prompt": "Quais SRs estao com {{resourceMember}} agora?",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "srs-by-resource", "--resource", "{{resourceMember}}", "--limit", "10"]
},
{
"id": "current-team-close-window",
"prompt": "Quais oportunidades fecham nos proximos 4 dias e tem recursos do meu time?",
"catalogRefs": ["SKILL.md"],
"args": ["--intent", "opportunities-current-team-close-window", "--from-date", "today", "--to-date", "+4d", "--limit", "10"]
},
{
"id": "ad-hoc-query",
"prompt": "Quero opportunityId, cliente, close date, booking e workload das oportunidades de 2026-05-02.",
"catalogRefs": ["SKILL.md"],
"args": ["--query", "--select", "opportunityId,customerName,closeDate,bookingValue,workloadAmount", "--where", "closeDate = DATE '2026-05-02'", "--render-sql"],
"live": false
}
]

21
tests/run.mjs Normal file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env node
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
const testsDir = path.dirname(fileURLToPath(import.meta.url));
const testFiles = [
path.join(testsDir, "functions.test.mjs"),
path.join(testsDir, "lib-contracts.test.mjs"),
path.join(testsDir, "sales-prompts.test.mjs"),
];
const child = spawn(process.execPath, ["--test", ...testFiles], {
stdio: "inherit",
env: process.env,
});
child.on("close", (code) => {
process.exitCode = code ?? 1;
});

View File

@@ -0,0 +1,536 @@
import fs from "node:fs/promises";
import path from "node:path";
import test from "node:test";
import assert from "node:assert/strict";
import {
argValue,
executionModes,
flagsInArgs,
runFetch,
testsDir,
withoutFlags,
} from "./helpers/cli.mjs";
import {
catalogMentionsIntent,
documentedFlags,
parseCurrentWorkloadDefaults,
parseDefaultWeekYear,
parsePrimaryCommercialSubjectArea,
parsePrimaryCommercialSourceName,
readSkillCatalogs,
} from "./helpers/catalogs.mjs";
import {
buildLiveExampleContext,
placeholderKeysForItem,
resolvePromptCase,
} from "./helpers/examples.mjs";
const liveEnabled = process.env.KNOWLEDGE_ONE_VIEW_LIVE === "1";
const catalogs = await readSkillCatalogs();
const promptCases = JSON.parse(
await fs.readFile(path.join(testsDir, "prompts", "sales-prompts.json"), "utf8")
);
function resolveArgs(args, examples = {}, { allowUnresolved = true } = {}) {
const weekYear = parseDefaultWeekYear(catalogs.scriptCatalog);
return args
.map((arg) => (arg === "catalog-default" ? String(weekYear) : arg))
.map((arg) => String(arg).replace(/\{\{([a-zA-Z0-9]+)\}\}/g, (match, key) => {
if (examples[key]) return examples[key];
if (allowUnresolved) return match;
throw new Error(`Missing live example value for {{${key}}}.`);
}));
}
function resolvedCase(item, examples = {}, { allowUnresolved = true } = {}) {
return resolvePromptCase(item, examples, { allowUnresolved });
}
function caseArgs(item, examples = {}, options = {}) {
return resolveArgs(resolvedCase(item, examples, options).args, examples, options);
}
function liveArgs(item, examples = {}, options = {}) {
const resolved = resolvedCase(item, examples, options);
return resolveArgs(resolved.liveArgs || withoutFlags(resolved.args, ["--render-sql"]), examples, options);
}
function promptNeedsInitialContext(prompt) {
return /\b(manager|abaixo|hierarquia|owners abaixo)\b/i.test(prompt);
}
function promptNeedsWeekReference(prompt) {
return /\bweek\b|\bwk\b|\bw\d+\b/i.test(prompt);
}
function globalParameterFlags(parameters) {
return new Set((parameters || []).map((parameter) => parameter.cli));
}
test("sales prompt commands are short, direct, and documented in references", () => {
const flagsFromReferences = documentedFlags(catalogs);
for (const item of promptCases) {
const args = caseArgs(item);
const modes = executionModes(args);
assert.deepEqual(modes, [args.includes("--intent") ? "--intent" : "--query"], item.id);
assert.equal(args.includes("--catalog"), false, `${item.id} should not start with discovery.`);
assert.equal(args.includes("--check-auth"), false, `${item.id} should not add auth checks to the normal fetch.`);
assert.ok(flagsInArgs(args).length <= 6, `${item.id} should remain easy for an agent to execute.`);
for (const flag of flagsInArgs(args)) {
assert.ok(flagsFromReferences.has(flag), `${item.id} uses undocumented flag ${flag}.`);
}
assert.ok(item.catalogRefs.includes("SKILL.md"), `${item.id} must start from SKILL.md.`);
if (promptNeedsInitialContext(item.prompt)) {
assert.ok(
item.catalogRefs.includes("references/initial-context-catalog.md"),
`${item.id} should point manager or hierarchy wording to initial-context-catalog.`
);
}
if (promptNeedsWeekReference(item.prompt)) {
assert.ok(
item.catalogRefs.includes("references/script-catalog.md#week-reference"),
`${item.id} should point week wording to the reference week table.`
);
}
const intent = argValue(args, "--intent");
if (intent) {
assert.equal(catalogMentionsIntent(catalogs, intent), true, `${item.id} intent is not mentioned in references.`);
}
}
});
test("sales prompt people examples are resolved dynamically, not hard-coded", () => {
const serializedPrompts = JSON.stringify(promptCases);
assert.doesNotMatch(serializedPrompts, /resource\.manager(?:\.a|\.b)?@oracle\.com/);
assert.doesNotMatch(serializedPrompts, /territory\.(?:owner|manager)@oracle\.com/);
assert.doesNotMatch(serializedPrompts, /resource\.member\b/);
const requiredPlaceholders = new Set([
"resourceManagerEmail",
"resourceManagerEmailA",
"resourceManagerEmailB",
"resourceManagerEmailList",
"territoryOwnerEmail",
"territoryManagerEmail",
"resourceMember",
]);
const usedPlaceholders = new Set(promptCases.flatMap((item) => placeholderKeysForItem(item)));
for (const placeholder of requiredPlaceholders) {
assert.ok(usedPlaceholders.has(placeholder), `Expected {{${placeholder}}} in prompt test definitions.`);
}
});
test("intent prompt commands match the live CLI contract without local flag copies", async () => {
const parameterCatalog = await runFetch(["--list-parameters"]);
const globalFlags = globalParameterFlags(parameterCatalog.json.parameters);
for (const item of promptCases) {
const args = caseArgs(item);
const intent = argValue(args, "--intent");
if (!intent) continue;
const result = await runFetch(["--describe-intent", intent]);
const intentFlags = new Set((result.json.intent.parameters || []).map((parameter) => parameter.cli));
assert.equal(result.json.intent.name, intent, item.id);
assert.equal(catalogMentionsIntent(catalogs, intent), true, item.id);
for (const flag of flagsInArgs(args)) {
if (flag === "--intent") continue;
assert.ok(globalFlags.has(flag), `${item.id} uses a flag missing from --list-parameters: ${flag}`);
assert.ok(
intentFlags.has(flag) || ["--limit"].includes(flag),
`${item.id} uses a flag that is not part of the intent contract: ${flag}`
);
}
if (["workloads-by-owner-current", "workloads-by-owner-manager-current"].includes(intent)) {
const expectedDefaults = parseCurrentWorkloadDefaults(catalogs, intent);
assert.match(result.json.intent.description, /current/i);
assert.ok(
(result.json.intent.parameters || []).some(
(parameter) => parameter.cli === "--quarter" && parameter.default === expectedDefaults.quarter
),
`${item.id} current workload intent must keep the documented quarter default in the catalog.`
);
assert.ok(catalogs.allText.includes(expectedDefaults.solution));
assert.ok(catalogs.allText.includes(expectedDefaults.revenueTypeGroup));
}
if (intent === "workloads-by-manager-resource-close-window") {
assert.match(result.json.intent.description, /Presales Involvement Aux - V1/);
assert.match(result.json.intent.description, /does not fetch SR details from DV - SE Team/);
assert.doesNotMatch(result.json.intent.description, /resolved SRs/i);
}
}
});
test("ad hoc sales prompt renders an org-wide opportunity query", async () => {
const item = promptCases.find((entry) => entry.id === "ad-hoc-query");
const args = caseArgs(item);
const result = await runFetch(args);
const selectAliases = argValue(args, "--select").split(",").map((value) => value.trim());
assert.equal(result.json.requestMode, "query");
assert.equal(result.json.scope.scopeMode, "org-wide");
assert.ok(catalogs.allText.includes(result.json.query.source), "Query source should be documented.");
assert.match(result.json.expandedSql, new RegExp(escapeRegExp(parsePrimaryCommercialSubjectArea(catalogs.apiMap))));
assert.doesNotMatch(result.json.expandedSql, /SEC_ARIA_SI-SR-TEAM/);
for (const alias of selectAliases) {
assert.ok(catalogs.allText.includes(alias), `Query alias ${alias} should be documented in references.`);
assert.ok(result.json.columns.includes(alias), `Rendered query should keep selected alias ${alias}.`);
}
});
test("org-wide query money aliases use the pipeline measure that Oracle DV accepts", async () => {
const result = await runFetch([
"--query",
"--select",
"opportunityId,customerName,closeDate,bookingValue,workloadAmount",
"--where",
"closeDate >= DATE '2026-04-26' AND closeDate <= DATE '2026-05-02' AND opportunityStatus IN ('Open','Won','Won Pending') AND cluster = 'Brazil'",
"--render-sql",
]);
assert.equal(result.json.requestMode, "query");
assert.equal(result.json.scope.scopeMode, "org-wide");
assert.match(result.json.expandedSql, /"Columns"\."Pipeline" AS bookingValue/);
assert.match(result.json.expandedSql, /"Columns"\."Pipeline" AS workloadAmount/);
assert.doesNotMatch(result.json.expandedSql, /"Columns"\."Opportunity Value" AS bookingValue/);
assert.doesNotMatch(result.json.expandedSql, /"Columns"\."Workload Amount" AS workloadAmount/);
assert.match(result.json.expandedSql, /"Columns"\."Cluster" = 'Brazil'/);
assert.match(result.json.expandedSql, /"Columns"\."Revenue Line Close Date" >= DATE '2026-04-26'/);
});
test("CLI rejects invalid limit values before backend execution", async () => {
for (const value of ["abc", "0", "-1", "1.5"]) {
const result = await runFetch(
[
"--render-sql",
"--query",
"--select",
"opportunityId",
"--limit",
value,
],
{ expectCode: 1 }
);
assert.match(result.stderr, new RegExp(`Unsupported --limit "${value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`));
assert.equal(result.stdout, "");
}
});
test(
"sales prompt commands run against Oracle DV when live mode is enabled",
{ skip: liveEnabled ? false : "set KNOWLEDGE_ONE_VIEW_LIVE=1 to run backend checks" },
async (t) => {
assert.ok(
process.env.ORACLE_SI_RUNTIME_HOME || process.env.ORACLE_SI_TEST_RUNTIME_HOME,
"Set ORACLE_SI_RUNTIME_HOME or ORACLE_SI_TEST_RUNTIME_HOME for live DV tests."
);
const sessionContext = await runFetch(
["--view", "data-quality-session-context", "--limit", "1"],
{ timeoutMs: 120000 }
);
assert.ok(Array.isArray(sessionContext.json.records), sessionContext.stdout || sessionContext.stderr);
assert.ok(sessionContext.json.apiMetrics.totalRowsPulledFromApi >= 0);
assert.ok(sessionContext.args.includes("--no-cache"), "The live warm-up must run with --no-cache.");
const liveExampleContext = await buildLiveExampleContext(catalogs);
const failures = [];
const tableRows = [];
for (const item of promptCases.filter((entry) => entry.live !== false)) {
const resolvedItem = {
...resolvedCase(item, liveExampleContext.examples, { allowUnresolved: false }),
placeholderKeys: placeholderKeysForItem(item),
};
let result = null;
let checks = [];
let commandError = null;
try {
result = await runFetch(liveArgs(item, liveExampleContext.examples, { allowUnresolved: false }), { timeoutMs: 180000 });
checks = evaluateLivePrompt(resolvedItem, result);
} catch (error) {
commandError = error;
checks = [
{
name: "command exited successfully",
pass: false,
actual: error.message,
expected: "JSON payload with exit code 0",
},
];
}
tableRows.push(buildPromptTableRow(resolvedItem, result, checks, commandError, liveExampleContext));
for (const check of checks) {
if (!check.pass) {
failures.push(`${item.id} :: ${check.name} :: expected ${formatValue(check.expected)}, got ${formatValue(check.actual)}`);
}
}
}
t.diagnostic(formatPromptResultsTable(tableRows));
assert.deepEqual(failures, [], failures.join("\n"));
}
);
function evaluateLivePrompt(item, result) {
const payload = result.json;
const expected = item.liveExpect || {};
const checks = [];
checks.push({
name: "command uses --no-cache",
pass: result.args.includes("--no-cache"),
actual: result.args.includes("--no-cache"),
expected: true,
});
checks.push({
name: "records array exists",
pass: Array.isArray(payload.records),
actual: Array.isArray(payload.records),
expected: true,
});
checks.push({
name: "api rows metric exists",
pass: typeof payload.apiMetrics?.totalRowsPulledFromApi === "number",
actual: typeof payload.apiMetrics?.totalRowsPulledFromApi,
expected: "number",
});
const intent = argValue(caseArgs(item), "--intent");
checks.push(
intent
? {
name: "intent echoed by CLI",
pass: payload.request?.intent === intent,
actual: payload.request?.intent,
expected: intent,
}
: {
name: "query mode echoed by CLI",
pass: payload.request?.mode === "query",
actual: payload.request?.mode,
expected: "query",
}
);
if (expected.scopeMode) {
checks.push({
name: "scope mode",
pass: payload.scope?.scopeMode === expected.scopeMode,
actual: payload.scope?.scopeMode,
expected: expected.scopeMode,
});
}
if (expected.dataSource === "primaryCommercial") {
const expectedSource = parsePrimaryCommercialSourceName(catalogs.apiMap);
checks.push({
name: "primary commercial data source from references/api-map.md",
pass: payload.request?.dataSource === expectedSource,
actual: payload.request?.dataSource,
expected: expectedSource,
});
}
if (expected.allowFallback === false) {
checks.push({
name: "no fallback for org-wide commercial prompt",
pass: fallbackUsed(payload) === false,
actual: fallbackUsed(payload),
expected: false,
});
}
if (expected.noDvSeTeamQueries === true) {
const dvSeTeamQueries = (payload.apiMetrics?.queries || [])
.filter((query) => query?.source === "DV - SE Team")
.map((query) => query.label);
checks.push({
name: "no DV - SE Team execution for involvement prompt",
pass: dvSeTeamQueries.length === 0,
actual: dvSeTeamQueries,
expected: [],
});
}
if (Number.isFinite(expected.minRecords)) {
checks.push({
name: "minimum final records",
pass: Array.isArray(payload.records) && payload.records.length >= expected.minRecords,
actual: Array.isArray(payload.records) ? payload.records.length : null,
expected: `>= ${expected.minRecords}`,
});
}
if (Number.isFinite(expected.minApiRows)) {
checks.push({
name: "minimum raw API rows",
pass: payload.apiMetrics?.totalRowsPulledFromApi >= expected.minApiRows,
actual: payload.apiMetrics?.totalRowsPulledFromApi,
expected: `>= ${expected.minApiRows}`,
});
}
return checks;
}
function buildPromptTableRow(item, result, checks, commandError = null, liveExampleContext = null) {
const passed = checks.every((check) => check.pass);
return {
id: item.id,
prompt: item.prompt,
resultado: buildResultCell(result, checks, passed),
trace: buildTraceCell(result, commandError, liveExampleContext, item),
escopo: buildScopeCell(result),
};
}
function buildResultCell(result, checks, passed) {
if (!result) {
return `FAIL; ${checks.map((check) => `${check.name}: ${formatValue(check.actual)}`).join("; ")}`;
}
const records = Array.isArray(result.json?.records) ? result.json.records.length : "n/a";
const apiRows = result.json?.apiMetrics?.totalRowsPulledFromApi ?? "n/a";
const failedChecks = checks.filter((check) => !check.pass).map((check) => check.name);
return [
passed ? "PASS" : "FAIL",
`records=${records}`,
`apiRows=${apiRows}`,
failedChecks.length > 0 ? `falhas=${failedChecks.join(", ")}` : null,
]
.filter(Boolean)
.join("; ");
}
function buildTraceCell(result, commandError = null, liveExampleContext = null, item = null) {
const resolverTrace = buildResolverTrace(liveExampleContext, item);
if (!result) {
return [
resolverTrace,
`fetch-sales-intelligence.mjs ${formatArgs(commandError?.args || [])} -> erro: ${commandError?.message || "unknown error"}`,
].filter(Boolean).join("; ");
}
const payload = result.json;
const commandTrace = `fetch-sales-intelligence.mjs ${formatArgs(result.args)} -> ok code=${result.code} durationMs=${Math.round(result.durationMs)}`;
const source = payload?.request?.dataSource || payload?.scope?.baseSource || "unknown source";
if (fallbackUsed(payload)) {
const primaryError = payload?.request?.primarySqlError || firstFallbackWarning(payload) || "primary source failed";
return [resolverTrace, `${commandTrace}; primary -> erro: ${primaryError}; fallback ${source} -> ok`]
.filter(Boolean)
.join("; ");
}
return [resolverTrace, `${commandTrace}; primary ${source} -> ok`].filter(Boolean).join("; ");
}
function buildScopeCell(result) {
if (!result?.json) return "sem payload; escopo desconhecido";
const payload = result.json;
const scopeMode = payload.scope?.scopeMode || payload.request?.scopeMode || "unknown";
const source = payload.request?.dataSource || payload.scope?.baseSource || "unknown source";
if (fallbackUsed(payload)) {
return `${scopeMode}; caiu para fallback ${source}; ${scopeDisclosure(payload)}`;
}
return `${scopeMode}; sem fallback; fonte ${source}; ${scopeDisclosure(payload)}`;
}
function formatPromptResultsTable(rows) {
const header = ["id", "prompt", "resultado", "trace da execucao do agente", "descricao escopo/fallback"];
const lines = [
`| ${header.join(" | ")} |`,
`| ${header.map(() => "---").join(" | ")} |`,
...rows.map((row) =>
`| ${markdownCell(row.id)} | ${markdownCell(row.prompt)} | ${markdownCell(row.resultado)} | ${markdownCell(row.trace)} | ${markdownCell(row.escopo)} |`
),
];
return lines.join("\n");
}
function formatArgs(args) {
return (args || [])
.map((arg) => (arg === "--runtime-home" ? "--runtime-home <test-runtime>" : arg))
.filter((arg, index, list) => list[index - 1] !== "--runtime-home <test-runtime>")
.join(" ");
}
function scopeDisclosure(payload) {
return payload?.scope?.disclosureLines?.join(" ") || payload?.scope?.explanation || "";
}
function buildResolverTrace(liveExampleContext, item) {
const keys = new Set(item?.placeholderKeys || placeholderKeysForItem(item || {}));
if (!keys.size || !liveExampleContext) return "";
const traces = [];
for (const trace of liveExampleContext.trace || []) {
if (!trace.profiles?.some((profile) => keys.has(profile))) continue;
const relevantProfiles = trace.profiles
.filter((profile) => keys.has(profile))
.map((profile) => `${profile}=${liveExampleContext.examples[profile]}`)
.join(", ");
traces.push(`${trace.script} ${formatArgs(trace.args)} -> ${trace.result}; selected ${relevantProfiles}`);
}
return traces.join("; ");
}
function firstFallbackWarning(payload) {
return (payload?.warnings || []).find((warning) => /fell back|fallback/i.test(warning));
}
function markdownCell(value) {
return String(value ?? "")
.replace(/\r?\n/g, "<br>")
.replace(/\|/g, "\\|");
}
function buildPromptDiagnostic(item, result, checks) {
return {
test: item.id,
prompt: item.prompt,
input: {
args: result ? result.args : liveArgs(item),
},
output: result
? {
records: Array.isArray(result.json?.records) ? result.json.records.length : null,
apiRows: result.json?.apiMetrics?.totalRowsPulledFromApi ?? null,
scopeMode: result.json?.scope?.scopeMode ?? null,
dataSource: result.json?.request?.dataSource ?? null,
fallbackUsed: fallbackUsed(result.json),
warnings: result.json?.warnings || [],
}
: null,
evaluation: checks.map((check) => ({
name: check.name,
passed: check.pass,
expected: check.expected,
actual: check.actual,
})),
};
}
function fallbackUsed(payload) {
const warningText = (payload?.warnings || []).join("\n");
return Boolean(
payload?.request?.fallbackUsed ||
payload?.scope?.fallbackUsed ||
/fell back|fallback used/i.test(warningText)
);
}
function formatValue(value) {
return typeof value === "string" ? value : JSON.stringify(value);
}
function escapeRegExp(value) {
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}