Files
playbook/antigravity-awesome-skills/tools/scripts/tests/pr_decision_manifest.test.js
T
2026-07-18 00:02:59 +00:00

208 lines
6.9 KiB
JavaScript

const assert = require("assert");
const fs = require("fs");
const os = require("os");
const path = require("path");
const { buildDecisionManifest, isSensitivePath } = require("../../lib/pr-decision");
const { getDirectDerivedChanges } = require("../../lib/workflow-contract");
const { appendGithubOutput, parseArgs } = require("../pr_decision_manifest.cjs");
const { changedFilesFromRecords } = require("../pr_preflight.cjs");
const docsRecord = {
status: "M",
old_path: "docs/users/faq.md",
new_path: "docs/users/faq.md",
old_mode: "100644",
new_mode: "100644",
old_oid: "1".repeat(40),
new_oid: "2".repeat(40),
similarity: null,
};
const preflight = {
baseRef: "origin/main",
headRef: "HEAD",
changedFiles: ["docs/users/faq.md"],
categories: ["docs"],
primaryCategory: "docs",
directDerivedChanges: [],
changeRecords: [docsRecord],
};
assert.strictEqual(isSensitivePath("tools/scripts/merge_batch.cjs"), true);
assert.strictEqual(isSensitivePath("docs/users/faq.md"), false);
assert.strictEqual(isSensitivePath("skills/group/example/SKILL.md"), false);
const sensitiveRenameRecord = {
status: "R",
old_path: ".github/workflows/old.md",
new_path: "docs/old.md",
old_mode: "100644",
new_mode: "100644",
old_oid: "1".repeat(40),
new_oid: "2".repeat(40),
similarity: 100,
};
assert.deepStrictEqual(
changedFilesFromRecords([sensitiveRenameRecord]),
[".github/workflows/old.md", "docs/old.md"],
);
assert.deepStrictEqual(
getDirectDerivedChanges(
changedFilesFromRecords([{
...sensitiveRenameRecord,
old_path: "plugins/generated.md",
new_path: "docs/generated.md",
}]),
{ derivedFiles: ["plugins/"] },
),
["plugins/generated.md"],
);
assert.strictEqual(
parseArgs([
"--preflight", "preflight.json",
"--evidence", "evidence.json",
"--write-github-output",
]).writeGithubOutput,
true,
);
{
const manifest = buildDecisionManifest({
preflight,
evidence: { base_ref: "origin/main", head_ref: "HEAD", changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.mode, "shadow");
assert.strictEqual(manifest.untrusted_advisory, true);
assert.strictEqual(manifest.route, "eligible_for_later_automation");
}
{
const renamedPreflight = {
...preflight,
changedFiles: changedFilesFromRecords([sensitiveRenameRecord]),
changeRecords: [sensitiveRenameRecord],
};
const manifest = buildDecisionManifest({
preflight: renamedPreflight,
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.route, "human_review");
assert.ok(manifest.change.sensitive_paths.includes(".github/workflows/old.md"));
assert.deepStrictEqual(manifest.change.change_records, [sensitiveRenameRecord]);
}
for (const [label, record] of [
["backslash", { ...sensitiveRenameRecord, status: "M", old_path: "docs\\foo.md", new_path: "docs\\foo.md", similarity: null }],
["symlink", { ...sensitiveRenameRecord, status: "M", old_path: "docs/foo.md", new_path: "docs/foo.md", new_mode: "120000", similarity: null }],
["executable", { ...sensitiveRenameRecord, status: "M", old_path: "docs/foo.md", new_path: "docs/foo.md", new_mode: "100755", similarity: null }],
["gitlink", { ...sensitiveRenameRecord, status: "M", old_path: "docs/foo.md", new_path: "docs/foo.md", new_mode: "160000", similarity: null }],
]) {
const manifest = buildDecisionManifest({
preflight: {
...preflight,
changedFiles: changedFilesFromRecords([record]),
changeRecords: [record],
},
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.route, "human_review", label);
assert.ok(manifest.reason_codes.includes("unsafe_change_records"), label);
assert.strictEqual(manifest.change.record_policy.approval_safe, false, label);
}
{
const manifest = buildDecisionManifest({
preflight: {
...preflight,
changedFiles: ["plugins/generated.md", "docs/generated.md"],
directDerivedChanges: ["plugins/generated.md"],
},
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.route, "block");
assert.ok(manifest.reason_codes.includes("direct_derived_changes"));
}
{
const manifest = buildDecisionManifest({
preflight: {
...preflight,
changedFiles: ["skills/example/SKILL.md"],
changeRecords: [{ ...docsRecord, old_path: "skills/example/SKILL.md", new_path: "skills/example/SKILL.md" }],
categories: ["skill"],
primaryCategory: "skill",
},
evidence: { changes: [{ skill_id: "example", change_type: "added" }], blocking: false, reasons: [] },
semanticReviewState: "unavailable",
});
assert.strictEqual(manifest.route, "human_review");
assert.ok(manifest.reason_codes.includes("semantic_review_unavailable"));
assert.ok(manifest.reason_codes.includes("canonical_skill_content_changed"));
}
{
const manifest = buildDecisionManifest({
preflight: { ...preflight, changeRecords: [] },
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.route, "human_review");
assert.ok(manifest.reason_codes.includes("unsafe_change_records"));
assert.ok(manifest.change.record_policy.reasons.includes("missing_change_records"));
}
{
const manifest = buildDecisionManifest({
preflight: { ...preflight, changedFiles: [], changeRecords: [] },
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "unknown",
});
assert.strictEqual(manifest.route, "eligible_for_later_automation");
}
{
const manifest = buildDecisionManifest({
preflight,
evidence: { changes: [], blocking: true, reasons: ["new_warning"] },
semanticReviewState: "available",
});
assert.strictEqual(manifest.route, "block");
assert.strictEqual(manifest.deterministic_gate.blocking, true);
}
assert.throws(
() => buildDecisionManifest({ preflight, evidence: {}, semanticReviewState: "unknown" }),
/evidence is incomplete/,
);
{
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "pr-decision-output-"));
const outputPath = path.join(directory, "github-output");
const previous = process.env.GITHUB_OUTPUT;
process.env.GITHUB_OUTPUT = outputPath;
try {
appendGithubOutput(buildDecisionManifest({
preflight,
evidence: { changes: [], blocking: false, reasons: [] },
semanticReviewState: "available",
}));
const output = fs.readFileSync(outputPath, "utf8");
assert.match(output, /^route=eligible_for_later_automation$/m);
assert.match(output, /^blocking=false$/m);
assert.match(output, /^changed_skills_count=0$/m);
} finally {
if (previous === undefined) delete process.env.GITHUB_OUTPUT;
else process.env.GITHUB_OUTPUT = previous;
fs.rmSync(directory, { recursive: true, force: true });
}
}
console.log("ok");