mason-context 0.16.3 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -688,7 +688,7 @@ async function findMissingPartners(resolvedRoot, changedFiles, existsOnDisk, all
688
688
 
689
689
  // src/review/evidence.ts
690
690
  import path10 from "path";
691
- import { z as z6 } from "zod";
691
+ import { z as z7 } from "zod";
692
692
 
693
693
  // src/review/evidence/vitest.ts
694
694
  import { z as z4 } from "zod";
@@ -904,20 +904,76 @@ function parseSarif(raw, sourceRoot) {
904
904
  };
905
905
  }
906
906
 
907
+ // src/review/evidence/check.ts
908
+ import { z as z6 } from "zod";
909
+ var schema3 = z6.object({
910
+ version: z6.literal(1),
911
+ commit: z6.string().regex(/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/).optional(),
912
+ results: z6.array(z6.object({
913
+ name: z6.string().min(1).max(1e3),
914
+ status: z6.enum(["passed", "failed", "skipped"]),
915
+ message: z6.string().max(1e5).optional(),
916
+ locations: z6.array(z6.object({
917
+ file: z6.string().min(1).max(4e3),
918
+ line: z6.number().int().positive().optional(),
919
+ column: z6.number().int().positive().optional()
920
+ })).max(100).default([])
921
+ })).max(1e5)
922
+ });
923
+ function parseCheck(raw, sourceRoot) {
924
+ const report = schema3.parse(raw);
925
+ const diagnostics = [], findings = [];
926
+ const counts = { total: report.results.length, passed: 0, failed: 0, skipped: 0 };
927
+ for (const [index2, result] of report.results.entries()) {
928
+ counts[result.status]++;
929
+ const locations = result.locations.flatMap((location2) => {
930
+ const file = evidencePath(location2.file, sourceRoot);
931
+ if (!file) {
932
+ diagnostics.push(`Check location is outside the declared checkout or invalid: ${location2.file}`);
933
+ return [];
934
+ }
935
+ return [{ ...location2, file }];
936
+ });
937
+ if (result.status === "failed") findings.push({
938
+ id: String(index2),
939
+ ...messagePreview([result.name, result.message].filter(Boolean).join("\n")),
940
+ severity: "error",
941
+ state: "active",
942
+ locations
943
+ });
944
+ }
945
+ if (!counts.total) diagnostics.push("No check results were recorded; an empty report is not passing evidence.");
946
+ if (counts.skipped) diagnostics.push(`${counts.skipped} checks were skipped; verification is incomplete.`);
947
+ return {
948
+ outcome: counts.failed ? "failed" : !counts.total ? "unavailable" : !counts.passed ? "skipped" : "passed",
949
+ counts,
950
+ findings,
951
+ incomplete: diagnostics.length > 0,
952
+ diagnostics,
953
+ ...report.commit ? { reportedCommits: [report.commit] } : {}
954
+ };
955
+ }
956
+
907
957
  // src/review/evidence.ts
908
- var checkSchema = z6.object({
909
- id: z6.string().min(1).max(100),
910
- kind: z6.enum(["tests", "static-analysis", "security", "complexity", "duplication"]),
911
- tool: z6.string().min(1).max(200),
912
- command: z6.string().min(1).max(2e3),
913
- commit: z6.string().regex(/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/).nullable().optional(),
914
- workingTreeClean: z6.boolean().optional(),
915
- source: z6.string().max(2e3).optional(),
916
- sourceRoot: z6.string().min(1).max(4e3).optional(),
917
- status: z6.enum(["completed", "skipped", "unavailable"]).default("completed"),
918
- reason: z6.string().min(1).max(2e3).optional(),
919
- exitCode: z6.number().int().nullable().optional(),
920
- report: z6.object({ format: z6.enum(["vitest-json", "sarif"]), path: z6.string().min(1).max(4e3) }).optional()
958
+ var checkSchema = z7.object({
959
+ id: z7.string().min(1).max(100),
960
+ kind: z7.enum(["tests", "static-analysis", "security", "complexity", "duplication", "documentation"]),
961
+ tool: z7.string().min(1).max(200),
962
+ command: z7.string().min(1).max(2e3),
963
+ commit: z7.string().regex(/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/).nullable().optional(),
964
+ workingTreeClean: z7.boolean().optional(),
965
+ source: z7.string().max(2e3).optional(),
966
+ sourceRoot: z7.string().min(1).max(4e3).optional(),
967
+ status: z7.enum(["completed", "skipped", "unavailable"]).default("completed"),
968
+ reason: z7.string().min(1).max(2e3).optional(),
969
+ exitCode: z7.number().int().nullable().optional(),
970
+ environment: z7.object({
971
+ toolVersion: z7.string().min(1).max(200),
972
+ runtime: z7.string().min(1).max(200).optional(),
973
+ platform: z7.string().min(1).max(200).optional(),
974
+ configuration: z7.array(z7.string().min(1).max(4e3)).max(100).optional()
975
+ }).optional(),
976
+ report: z7.object({ format: z7.enum(["vitest-json", "sarif", "mason-check-json"]), path: z7.string().min(1).max(4e3) }).optional()
921
977
  });
922
978
  function relativeArtifact(root, file) {
923
979
  const relative = path10.isAbsolute(file) ? path10.relative(root, file) : file;
@@ -959,7 +1015,7 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
959
1015
  let manifest, raw;
960
1016
  try {
961
1017
  manifest = relativeArtifact(root, supplied);
962
- raw = z6.object({ version: z6.literal(1), checks: z6.array(z6.unknown()) }).parse(await readStoreJson(root, manifest));
1018
+ raw = z7.object({ version: z7.literal(1), checks: z7.array(z7.unknown()) }).parse(await readStoreJson(root, manifest));
963
1019
  } catch (error) {
964
1020
  output.diagnostics.push(`${supplied}: ${String(error)}`);
965
1021
  continue;
@@ -998,7 +1054,8 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
998
1054
  counts: {},
999
1055
  incomplete: false,
1000
1056
  diagnostics: [],
1001
- truncated: false
1057
+ truncated: false,
1058
+ ...check.environment ? { environment: check.environment } : {}
1002
1059
  };
1003
1060
  output.checks.push(result);
1004
1061
  if (check.workingTreeClean !== true) result.diagnostics.push("The check's working tree was dirty or not recorded; its results cannot be attributed to the claimed commit alone.");
@@ -1011,13 +1068,13 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
1011
1068
  }
1012
1069
  try {
1013
1070
  if (!check.report) throw new Error("Completed check has no report artifact.");
1014
- if (check.kind === "tests" !== (check.report.format === "vitest-json")) throw new Error("Test checks require vitest-json; analysis checks require sarif.");
1071
+ if (check.report.format !== "mason-check-json" && check.kind === "tests" !== (check.report.format === "vitest-json")) throw new Error("Test checks require vitest-json or mason-check-json; analysis checks require sarif or mason-check-json.");
1015
1072
  const file = relativeArtifact(root, check.report.path);
1016
1073
  const report = await readStoreJson(root, file);
1017
1074
  if (report === null) throw new Error(`Report artifact is missing: ${file}`);
1018
1075
  const sourceRoot = check.sourceRoot ?? root;
1019
1076
  if (!path10.posix.isAbsolute(sourceRoot) && !/^[A-Za-z]:[\\/]/.test(sourceRoot)) throw new Error("sourceRoot must identify the absolute checkout root on the check runner.");
1020
- const parsed = check.report.format === "vitest-json" ? parseVitest(report, sourceRoot) : parseSarif(report, sourceRoot);
1077
+ const parsed = check.report.format === "vitest-json" ? parseVitest(report, sourceRoot) : check.report.format === "mason-check-json" ? parseCheck(report, sourceRoot) : parseSarif(report, sourceRoot);
1021
1078
  result.outcome = parsed.outcome;
1022
1079
  result.counts = parsed.counts;
1023
1080
  result.incomplete = parsed.incomplete;
@@ -1037,7 +1094,7 @@ async function collectReviewEvidence(root, manifests, changedFiles, decisions, d
1037
1094
  result.outcome = "failed";
1038
1095
  result.diagnostics.push(`Check command exited ${check.exitCode} despite a report with no active failures.`);
1039
1096
  }
1040
- if (check.report.format === "vitest-json" && pairs === void 0) {
1097
+ if (check.kind === "tests" && pairs === void 0) {
1041
1098
  try {
1042
1099
  pairs = (await buildTestMap(root)).paired;
1043
1100
  } catch (error) {
@@ -1259,6 +1316,10 @@ function evidenceSummary(report) {
1259
1316
  for (const check of evidence.checks) {
1260
1317
  lines.push(` [${check.kind}] ${display(check.id)}: ${check.outcome}, ${check.freshness} (${display(check.tool)})`);
1261
1318
  lines.push(` command: ${display(check.command)}; tested commit: ${check.commit ?? "unknown"}`);
1319
+ if (check.environment) {
1320
+ lines.push(` environment: ${display(check.tool)} ${display(check.environment.toolVersion)}` + (check.environment.runtime ? `; ${display(check.environment.runtime)}` : "") + (check.environment.platform ? `; ${display(check.environment.platform)}` : ""));
1321
+ if (check.environment.configuration?.length) lines.push(" configuration: " + check.environment.configuration.map((value) => display(value)).join(", "));
1322
+ }
1262
1323
  lines.push(` source: ${display(check.source ?? check.manifest)}; report: ${display(check.report?.path ?? "none")}`);
1263
1324
  if (Object.keys(check.counts).length) lines.push(` counts: ${JSON.stringify(check.counts)}`);
1264
1325
  for (const diagnostic of check.diagnostics.slice(0, 5)) lines.push(` note: ${display(diagnostic)}`);