@codyswann/lisa 3.47.10 → 3.48.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.
Files changed (106) hide show
  1. package/dist/cli/doctor-render.d.ts +22 -0
  2. package/dist/cli/doctor-render.d.ts.map +1 -0
  3. package/dist/cli/doctor-render.js +27 -0
  4. package/dist/cli/doctor-render.js.map +1 -0
  5. package/dist/cli/doctor.d.ts +15 -0
  6. package/dist/cli/doctor.d.ts.map +1 -1
  7. package/dist/cli/doctor.js +2 -9
  8. package/dist/cli/doctor.js.map +1 -1
  9. package/dist/cli/gate-report-cells.d.ts +101 -0
  10. package/dist/cli/gate-report-cells.d.ts.map +1 -0
  11. package/dist/cli/gate-report-cells.js +269 -0
  12. package/dist/cli/gate-report-cells.js.map +1 -0
  13. package/dist/cli/gate-report-config.d.ts +28 -0
  14. package/dist/cli/gate-report-config.d.ts.map +1 -0
  15. package/dist/cli/gate-report-config.js +33 -0
  16. package/dist/cli/gate-report-config.js.map +1 -0
  17. package/dist/cli/gate-report-executors.d.ts +62 -0
  18. package/dist/cli/gate-report-executors.d.ts.map +1 -0
  19. package/dist/cli/gate-report-executors.js +218 -0
  20. package/dist/cli/gate-report-executors.js.map +1 -0
  21. package/dist/cli/gate-report-preview.d.ts +27 -0
  22. package/dist/cli/gate-report-preview.d.ts.map +1 -0
  23. package/dist/cli/gate-report-preview.js +286 -0
  24. package/dist/cli/gate-report-preview.js.map +1 -0
  25. package/dist/cli/gate-report-registry.d.ts +68 -0
  26. package/dist/cli/gate-report-registry.d.ts.map +1 -0
  27. package/dist/cli/gate-report-registry.js +52 -0
  28. package/dist/cli/gate-report-registry.js.map +1 -0
  29. package/dist/cli/gate-report-ruleset.d.ts +60 -0
  30. package/dist/cli/gate-report-ruleset.d.ts.map +1 -0
  31. package/dist/cli/gate-report-ruleset.js +132 -0
  32. package/dist/cli/gate-report-ruleset.js.map +1 -0
  33. package/dist/cli/gate-report-skip-jobs.d.ts +34 -0
  34. package/dist/cli/gate-report-skip-jobs.d.ts.map +1 -0
  35. package/dist/cli/gate-report-skip-jobs.js +42 -0
  36. package/dist/cli/gate-report-skip-jobs.js.map +1 -0
  37. package/dist/cli/gate-report-summary.d.ts +18 -0
  38. package/dist/cli/gate-report-summary.d.ts.map +1 -0
  39. package/dist/cli/gate-report-summary.js +80 -0
  40. package/dist/cli/gate-report-summary.js.map +1 -0
  41. package/dist/cli/gate-report-types.d.ts +206 -0
  42. package/dist/cli/gate-report-types.d.ts.map +1 -0
  43. package/dist/cli/gate-report-types.js +19 -0
  44. package/dist/cli/gate-report-types.js.map +1 -0
  45. package/dist/cli/gate-report.d.ts +35 -0
  46. package/dist/cli/gate-report.d.ts.map +1 -0
  47. package/dist/cli/gate-report.js +317 -0
  48. package/dist/cli/gate-report.js.map +1 -0
  49. package/dist/cli/ui-github-repo-gh.d.ts +14 -0
  50. package/dist/cli/ui-github-repo-gh.d.ts.map +1 -1
  51. package/dist/cli/ui-github-repo-gh.js +6 -1
  52. package/dist/cli/ui-github-repo-gh.js.map +1 -1
  53. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  54. package/dist/core/upstream-evidence-manifest.js +18 -0
  55. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  56. package/package.json +1 -1
  57. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-agy/plugin.json +1 -1
  60. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  63. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-expo-agy/plugin.json +1 -1
  70. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  75. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  79. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  80. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  84. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  85. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  90. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  94. package/plugins/lisa-rails-agy/plugin.json +1 -1
  95. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  99. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  100. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  104. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  105. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  106. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
@@ -0,0 +1,68 @@
1
+ /** One gate as the shipped registry defines it. */
2
+ export interface RegistryGate {
3
+ readonly label: string;
4
+ readonly summary: string;
5
+ readonly task?: string;
6
+ readonly taskAt?: Readonly<Record<string, string>>;
7
+ readonly moments: readonly string[];
8
+ readonly work?: string;
9
+ readonly costly?: boolean;
10
+ readonly mayRewrite?: boolean;
11
+ }
12
+ /** One gate as `resolveMoment` returns it. */
13
+ export interface ResolvedGate {
14
+ readonly id: string;
15
+ readonly level: string;
16
+ readonly mode: string;
17
+ readonly awaits: string | null;
18
+ readonly task: string | null;
19
+ readonly command: string | null;
20
+ readonly label: string;
21
+ }
22
+ /** One `skip_jobs` token's migration. */
23
+ export interface SkipJobResolution {
24
+ readonly token: string;
25
+ readonly status: string;
26
+ readonly gate: string | null;
27
+ readonly declaration: string | null;
28
+ }
29
+ /** The config `readGates` parses out of `.lisa.config.json`. */
30
+ export interface ParsedGateConfig {
31
+ readonly runner: string;
32
+ readonly gates: Record<string, unknown>;
33
+ }
34
+ /** The slice of the shipped registry this report calls. */
35
+ export interface GateRegistryModule {
36
+ readonly REGISTRY: Readonly<Record<string, RegistryGate>>;
37
+ readonly MOMENTS: readonly string[];
38
+ readonly MOMENT_FAMILIES: readonly string[];
39
+ readonly INTERCEPTORS: Readonly<Record<string, string>>;
40
+ readonly QUALITY_JOB_GATES: Readonly<Record<string, string>>;
41
+ readonly DEFAULT_RUNNER: string;
42
+ readonly readGates: (cwd: string) => ParsedGateConfig;
43
+ readonly validateGates: (gates: Record<string, unknown>) => string[];
44
+ readonly resolveMoment: (options: {
45
+ gates: Record<string, unknown>;
46
+ moment: string;
47
+ runner?: string;
48
+ includeOff?: boolean;
49
+ }) => ResolvedGate[];
50
+ readonly contextsFor: (gates: Record<string, unknown>, options?: {
51
+ moment?: string;
52
+ workflowName?: string;
53
+ }) => string[];
54
+ readonly isMoment: (moment: string) => boolean;
55
+ readonly momentFamily: (moment: string) => string;
56
+ readonly skipJobMigration: (token: string, moment: string) => SkipJobResolution;
57
+ }
58
+ /**
59
+ * Locate the shipped registry inside the running Lisa package.
60
+ * @returns Absolute path, or null when it cannot be found
61
+ */
62
+ export declare function resolveGateRegistryPath(): string | null;
63
+ /**
64
+ * Import the shipped registry.
65
+ * @returns The registry module, or null when it is not installed
66
+ */
67
+ export declare function loadGateRegistry(): Promise<GateRegistryModule | null>;
68
+ //# sourceMappingURL=gate-report-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-registry.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Load the gate registry the report is derived from.
3
+ *
4
+ * Deliberately the running Lisa package's copy rather than the project's
5
+ * `scripts/lisa-gates.mjs`, for the reason `doctor-skip-jobs-migration` already
6
+ * gives: both are the same file in a healthy repository, but a stale project
7
+ * copy answers with a table describing a workflow that is no longer there. It
8
+ * matters twice over here — this repository's own `scripts/` holds neither
9
+ * shipped script, so a report that read the project copy would report nothing
10
+ * at all when run against Lisa itself.
11
+ * @module cli/gate-report-registry
12
+ */
13
+ import { existsSync } from "node:fs";
14
+ import * as path from "node:path";
15
+ import { fileURLToPath, pathToFileURL } from "node:url";
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ /** Package-relative location of the shipped registry. */
18
+ const REGISTRY_RELATIVE = path.join("all", "copy-overwrite", "scripts", "lisa-gates.mjs");
19
+ /**
20
+ * Walk parents until a package-root-relative file exists.
21
+ * @param startDir - Directory to start searching from
22
+ * @param relativePath - Path under the package root
23
+ * @returns Absolute path, or null when no ancestor holds it
24
+ */
25
+ function walkForPackageFile(startDir, relativePath) {
26
+ const candidate = path.join(startDir, relativePath);
27
+ if (existsSync(candidate))
28
+ return candidate;
29
+ const parent = path.dirname(startDir);
30
+ return parent === startDir ? null : walkForPackageFile(parent, relativePath);
31
+ }
32
+ /**
33
+ * Locate the shipped registry inside the running Lisa package.
34
+ * @returns Absolute path, or null when it cannot be found
35
+ */
36
+ export function resolveGateRegistryPath() {
37
+ const fromPackageRoot = path.join(__dirname, "..", "..", REGISTRY_RELATIVE);
38
+ if (existsSync(fromPackageRoot))
39
+ return fromPackageRoot;
40
+ return walkForPackageFile(__dirname, REGISTRY_RELATIVE);
41
+ }
42
+ /**
43
+ * Import the shipped registry.
44
+ * @returns The registry module, or null when it is not installed
45
+ */
46
+ export async function loadGateRegistry() {
47
+ const script = resolveGateRegistryPath();
48
+ if (script === null)
49
+ return null;
50
+ return (await import(pathToFileURL(script).href));
51
+ }
52
+ //# sourceMappingURL=gate-report-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-registry.js","sourceRoot":"","sources":["../../src/cli/gate-report-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,yDAAyD;AACzD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CACjC,KAAK,EACL,gBAAgB,EAChB,SAAS,EACT,gBAAgB,CACjB,CAAC;AAmEF;;;;;GAKG;AACH,SAAS,kBAAkB,CACzB,QAAgB,EAChB,YAAoB;IAEpB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAC5E,IAAI,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO,eAAe,CAAC;IACxD,OAAO,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,uBAAuB,EAAE,CAAC;IACzC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,CAAC,MAAM,MAAM,CAClB,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAC3B,CAAkC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Tier 2 — what a repository ruleset actually requires.
3
+ *
4
+ * `contextsFor()` derives what the required contexts *should* be; the ruleset
5
+ * says what they *are*; nothing compares the two, so they are only ever equal
6
+ * by hand. This module makes the comparison, and it is the one part of the
7
+ * report that needs a network call.
8
+ *
9
+ * The failure mode it exists to avoid is the easy one - an unauthenticated run
10
+ * reporting "this gate does not block a merge" when it simply did not look.
11
+ * Every failure path here lands on `unknown` carrying a reason that separates
12
+ * `not-authenticated` from `call-failed` from `offline`, and no path lands on
13
+ * a verdict.
14
+ * @module cli/gate-report-ruleset
15
+ */
16
+ import type { Finding, RulesetComparison } from "./gate-report-types.js";
17
+ /** Reads the required status contexts guarding the default branch. */
18
+ export type RequiredContextsReader = (projectRoot: string) => Promise<readonly string[]>;
19
+ /**
20
+ * Pull every required status-check context out of a branch-rules payload.
21
+ * @param payload - Parsed `rules/branches/{branch}` response
22
+ * @returns Contexts, sorted and de-duplicated
23
+ */
24
+ export declare function extractRequiredContexts(payload: unknown): string[];
25
+ /**
26
+ * Read the live ruleset through the `gh` CLI.
27
+ * @param projectRoot - Project root, so `gh` resolves the right remote
28
+ * @returns The required contexts guarding the default branch
29
+ */
30
+ export declare const defaultRequiredContextsReader: RequiredContextsReader;
31
+ /**
32
+ * Turn a `gh` failure into the narrowest honest reason.
33
+ * @param error - Whatever the call threw
34
+ * @returns A machine reason and a human message
35
+ */
36
+ export declare function classifyGhFailure(error: unknown): {
37
+ reason: string;
38
+ message: string;
39
+ };
40
+ /**
41
+ * Read the live required contexts, degrading to `unknown` and never to a pass.
42
+ * @param options - Probe inputs
43
+ * @param options.projectRoot - Project root
44
+ * @param options.offline - Whether the run may make a network call
45
+ * @param options.read - Injectable reader
46
+ * @returns The contexts, or an honest unknown
47
+ */
48
+ export declare function readRequiredContexts(options: {
49
+ projectRoot: string;
50
+ offline: boolean;
51
+ read: RequiredContextsReader;
52
+ }): Promise<Finding<readonly string[]>>;
53
+ /**
54
+ * Compare the contexts a declaration implies with the ones a ruleset requires.
55
+ * @param declared - Contexts derived from the gates block
56
+ * @param required - Contexts the ruleset actually requires
57
+ * @returns The three-way comparison
58
+ */
59
+ export declare function compareContexts(declared: readonly string[], required: readonly string[]): RulesetComparison;
60
+ //# sourceMappingURL=gate-report-ruleset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-ruleset.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-ruleset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAMzE,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG,CACnC,WAAW,EAAE,MAAM,KAChB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;AAsBhC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAOlE;AAkCD;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,sBAczC,CAAC;AAEJ;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAqBA;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,sBAAsB,CAAC;CAC9B,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC,CAetC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,iBAAiB,CAcnB"}
@@ -0,0 +1,132 @@
1
+ import { runGh } from "./ui-github-repo-gh.js";
2
+ /** Child-process budget for one `gh` call. */
3
+ const GH_TIMEOUT_MS = 10_000;
4
+ /**
5
+ * The required status-check contexts one branch rule names.
6
+ * @param rule - One entry of the branch-rules response
7
+ * @returns Its contexts, in the order the payload lists them
8
+ */
9
+ function contextsOfRule(rule) {
10
+ if (rule === null || typeof rule !== "object")
11
+ return [];
12
+ const parameters = Reflect.get(rule, "parameters");
13
+ if (parameters === null || typeof parameters !== "object")
14
+ return [];
15
+ const checks = Reflect.get(parameters, "required_status_checks");
16
+ if (!Array.isArray(checks))
17
+ return [];
18
+ return checks
19
+ .map(check => check === null || typeof check !== "object"
20
+ ? undefined
21
+ : Reflect.get(check, "context"))
22
+ .filter((context) => typeof context === "string");
23
+ }
24
+ /**
25
+ * Pull every required status-check context out of a branch-rules payload.
26
+ * @param payload - Parsed `rules/branches/{branch}` response
27
+ * @returns Contexts, sorted and de-duplicated
28
+ */
29
+ export function extractRequiredContexts(payload) {
30
+ if (!Array.isArray(payload)) {
31
+ throw new TypeError("Branch rules response was not an array");
32
+ }
33
+ return [...new Set(payload.flatMap(contextsOfRule))].sort((left, right) => left.localeCompare(right));
34
+ }
35
+ /**
36
+ * The repository slug and default branch, from `gh repo view`.
37
+ * @param projectRoot - Project root
38
+ * @param signal - Cancellation signal
39
+ * @returns Slug and branch
40
+ */
41
+ async function readRepoTarget(projectRoot, signal) {
42
+ const view = await runGh(["repo", "view", "--json", "nameWithOwner,defaultBranchRef"], projectRoot, GH_TIMEOUT_MS, signal);
43
+ const parsed = JSON.parse(view);
44
+ if (parsed === null || typeof parsed !== "object") {
45
+ throw new TypeError("gh repo view did not return an object");
46
+ }
47
+ const slug = Reflect.get(parsed, "nameWithOwner");
48
+ const branchRef = Reflect.get(parsed, "defaultBranchRef");
49
+ const branch = branchRef !== null && typeof branchRef === "object"
50
+ ? Reflect.get(branchRef, "name")
51
+ : undefined;
52
+ if (typeof slug !== "string" || typeof branch !== "string") {
53
+ throw new TypeError("gh repo view omitted the repository or its branch");
54
+ }
55
+ return { slug, branch };
56
+ }
57
+ /**
58
+ * Read the live ruleset through the `gh` CLI.
59
+ * @param projectRoot - Project root, so `gh` resolves the right remote
60
+ * @returns The required contexts guarding the default branch
61
+ */
62
+ export const defaultRequiredContextsReader = async (projectRoot) => {
63
+ const controller = new AbortController();
64
+ const { slug, branch } = await readRepoTarget(projectRoot, controller.signal);
65
+ const rules = await runGh(["api", `repos/${slug}/rules/branches/${branch}`], projectRoot, GH_TIMEOUT_MS, controller.signal);
66
+ return extractRequiredContexts(JSON.parse(rules));
67
+ };
68
+ /**
69
+ * Turn a `gh` failure into the narrowest honest reason.
70
+ * @param error - Whatever the call threw
71
+ * @returns A machine reason and a human message
72
+ */
73
+ export function classifyGhFailure(error) {
74
+ const text = error instanceof Error ? error.message : String(error);
75
+ if (text.includes("ENOENT")) {
76
+ return {
77
+ reason: "gh-not-installed",
78
+ message: "The GitHub CLI is not installed, so branch protection could not be read. Nothing here claims a gate does or does not block a merge.",
79
+ };
80
+ }
81
+ if (/auth|credential|HTTP 401|HTTP 403/i.test(text)) {
82
+ return {
83
+ reason: "not-authenticated",
84
+ message: "The GitHub CLI is not authenticated for this repository's host, so branch protection could not be read. Nothing here claims a gate does or does not block a merge.",
85
+ };
86
+ }
87
+ return {
88
+ reason: "call-failed",
89
+ message: "Reading branch protection failed, so what a merge actually requires is unknown for this run.",
90
+ };
91
+ }
92
+ /**
93
+ * Read the live required contexts, degrading to `unknown` and never to a pass.
94
+ * @param options - Probe inputs
95
+ * @param options.projectRoot - Project root
96
+ * @param options.offline - Whether the run may make a network call
97
+ * @param options.read - Injectable reader
98
+ * @returns The contexts, or an honest unknown
99
+ */
100
+ export async function readRequiredContexts(options) {
101
+ if (options.offline) {
102
+ return {
103
+ state: "unknown",
104
+ reason: "offline",
105
+ message: "This run was asked not to use the network, so branch protection was not read. The data exists; this run did not fetch it.",
106
+ };
107
+ }
108
+ try {
109
+ const value = await options.read(options.projectRoot);
110
+ return { state: "verified", value };
111
+ }
112
+ catch (error) {
113
+ return { state: "unknown", ...classifyGhFailure(error) };
114
+ }
115
+ }
116
+ /**
117
+ * Compare the contexts a declaration implies with the ones a ruleset requires.
118
+ * @param declared - Contexts derived from the gates block
119
+ * @param required - Contexts the ruleset actually requires
120
+ * @returns The three-way comparison
121
+ */
122
+ export function compareContexts(declared, required) {
123
+ const requiredSet = new Set(required);
124
+ const declaredSet = new Set(declared);
125
+ const sort = (values) => [...values].sort((left, right) => left.localeCompare(right));
126
+ return {
127
+ matched: sort(declared.filter(context => requiredSet.has(context))),
128
+ declaredNotRequired: sort(declared.filter(context => !requiredSet.has(context))),
129
+ requiredNotDeclared: sort(required.filter(context => !declaredSet.has(context))),
130
+ };
131
+ }
132
+ //# sourceMappingURL=gate-report-ruleset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-ruleset.js","sourceRoot":"","sources":["../../src/cli/gate-report-ruleset.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The `skip_jobs` tokens a project still forwards, and what replaces each.
3
+ *
4
+ * `SKIP_JOB_TOKENS` has thirty-one entries and `QUALITY_JOB_GATES` has
5
+ * eighteen; the gap is the point. A token with no gate cannot be migrated, and
6
+ * being wrong about which gate replaces a token does not break a build — it
7
+ * declares the WRONG gate `off`, so a check silently stops running while the
8
+ * configuration reads deliberate.
9
+ * @module cli/gate-report-skip-jobs
10
+ */
11
+ import type { GateRegistryModule } from "./gate-report-registry.js";
12
+ import type { Finding, SkipJobRow } from "./gate-report-types.js";
13
+ /** Reads the tokens a project's own `ci.yml` forwards. */
14
+ export type SkipJobTokensReader = (projectRoot: string) => Promise<readonly string[]>;
15
+ /**
16
+ * Read the tokens from the project's own `ci.yml`.
17
+ * @param projectRoot - Project root
18
+ * @returns The forwarded tokens
19
+ */
20
+ export declare const defaultSkipJobTokensReader: SkipJobTokensReader;
21
+ /**
22
+ * Resolve every forwarded token through the shipped migration table.
23
+ * @param options - Inputs
24
+ * @param options.registry - The shipped registry
25
+ * @param options.projectRoot - Project root
26
+ * @param options.read - Injectable token reader
27
+ * @returns The rows, or a stated reason there are none to report
28
+ */
29
+ export declare function buildSkipJobRows(options: {
30
+ registry: GateRegistryModule;
31
+ projectRoot: string;
32
+ read: SkipJobTokensReader;
33
+ }): Promise<Finding<readonly SkipJobRow[]>>;
34
+ //# sourceMappingURL=gate-report-skip-jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-skip-jobs.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-skip-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAMlE,0DAA0D;AAC1D,MAAM,MAAM,mBAAmB,GAAG,CAChC,WAAW,EAAE,MAAM,KAChB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,mBACiC,CAAC;AAE3E;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,mBAAmB,CAAC;CAC3B,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC,CAwB1C"}
@@ -0,0 +1,42 @@
1
+ import { parseCiWorkflowInputs } from "./ui-ci-quality-jobs-parse.js";
2
+ /** The moment `quality.yml` resolves gates at when a caller declares none. */
3
+ const DEFAULT_MOMENT = "pull-request";
4
+ /**
5
+ * Read the tokens from the project's own `ci.yml`.
6
+ * @param projectRoot - Project root
7
+ * @returns The forwarded tokens
8
+ */
9
+ export const defaultSkipJobTokensReader = async (projectRoot) => (await parseCiWorkflowInputs(projectRoot)).skipJobs;
10
+ /**
11
+ * Resolve every forwarded token through the shipped migration table.
12
+ * @param options - Inputs
13
+ * @param options.registry - The shipped registry
14
+ * @param options.projectRoot - Project root
15
+ * @param options.read - Injectable token reader
16
+ * @returns The rows, or a stated reason there are none to report
17
+ */
18
+ export async function buildSkipJobRows(options) {
19
+ // `Promise.resolve().then` rather than a bare call, so a reader that throws
20
+ // synchronously lands in the same not-applicable branch as one that rejects.
21
+ const tokens = await Promise.resolve()
22
+ .then(() => options.read(options.projectRoot))
23
+ .catch(() => undefined);
24
+ if (tokens === undefined) {
25
+ return {
26
+ state: "not-applicable",
27
+ reason: "no-quality-caller",
28
+ message: "This project has no workflow calling Lisa's quality workflow, so it forwards no skip_jobs tokens.",
29
+ };
30
+ }
31
+ const rows = tokens.map(token => {
32
+ const resolution = options.registry.skipJobMigration(token, DEFAULT_MOMENT);
33
+ return {
34
+ token: resolution.token,
35
+ status: resolution.status,
36
+ gate: resolution.gate,
37
+ declaration: resolution.declaration,
38
+ };
39
+ });
40
+ return { state: "verified", value: rows };
41
+ }
42
+ //# sourceMappingURL=gate-report-skip-jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-skip-jobs.js","sourceRoot":"","sources":["../../src/cli/gate-report-skip-jobs.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,8EAA8E;AAC9E,MAAM,cAAc,GAAG,cAAc,CAAC;AAOtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,KAAK,EAAC,WAAW,EAAC,EAAE,CAAC,CAAC,MAAM,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAItC;IACC,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE;SACnC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;SAC7C,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC1B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EACL,mGAAmG;SACtG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QAC5E,OAAO;YACL,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,WAAW,EAAE,UAAU,CAAC,WAAW;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Counts for the gate report, each stating its denominator and its unknowns.
3
+ *
4
+ * A header reading "31 of 34 healthy" where three were never checked is the
5
+ * defect this report is organised against, so nothing here folds an `unknown`
6
+ * into a green count. `bucketUnknown` is a first-class number sitting beside
7
+ * A/B/C/D rather than being absorbed into D.
8
+ * @module cli/gate-report-summary
9
+ */
10
+ import type { GateReportRow, GateReportSummary } from "./gate-report-types.js";
11
+ /**
12
+ * Summarise the report.
13
+ * @param rows - Every gate row
14
+ * @param momentCount - Moments on the report's axis
15
+ * @returns The summary block
16
+ */
17
+ export declare function summarise(rows: readonly GateReportRow[], momentCount: number): GateReportSummary;
18
+ //# sourceMappingURL=gate-report-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-summary.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAGV,aAAa,EACb,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAkEhC;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,aAAa,EAAE,EAC9B,WAAW,EAAE,MAAM,GAClB,iBAAiB,CAsBnB"}
@@ -0,0 +1,80 @@
1
+ /** Levels that put a gate into service. */
2
+ const ACTIVE_LEVELS = new Set(["required", "optional"]);
3
+ /**
4
+ * Whether a gate carries at least one live declaration anywhere.
5
+ * @param row - One gate's row
6
+ * @returns True when some moment declares it required or optional
7
+ */
8
+ function isGoverned(row) {
9
+ return row.moments.some(cell => ACTIVE_LEVELS.has(cell.declaration));
10
+ }
11
+ /**
12
+ * Whether a gate is mentioned by the settings file only to be turned off.
13
+ * @param row - One gate's row
14
+ * @returns True when every declaration is `off` and there is at least one
15
+ */
16
+ function isOffOnly(row) {
17
+ return (!isGoverned(row) && row.moments.some(cell => cell.declaration === "off"));
18
+ }
19
+ /**
20
+ * Whether an undeclared pair is proved anyway by a written-in command.
21
+ *
22
+ * This is bucket B stated as a number, and it is the sentence a non-technical
23
+ * operator can act on: the check is running, so the repository looks healthy,
24
+ * and the settings file has no say over it.
25
+ * @param cell - One (gate, moment) pair
26
+ * @returns True when nothing declares it and a script runs it regardless
27
+ */
28
+ function isProvedAnyway(cell) {
29
+ return (!ACTIVE_LEVELS.has(cell.declaration) &&
30
+ cell.executors.some(entry => entry.kind !== "gate-runner"));
31
+ }
32
+ /**
33
+ * Whether a declared pair resolves to a command the project does not have.
34
+ * @param cell - One (gate, moment) pair
35
+ * @returns True when it is bucket C's sharp case
36
+ */
37
+ function isDeclaredWithoutCommand(cell) {
38
+ return (ACTIVE_LEVELS.has(cell.declaration) &&
39
+ cell.commandExists.state === "verified" &&
40
+ !cell.commandExists.value);
41
+ }
42
+ /**
43
+ * Count the cells classified into one bucket.
44
+ * @param cells - Every legal cell
45
+ * @param bucket - The bucket to count
46
+ * @returns The count
47
+ */
48
+ function countBucket(cells, bucket) {
49
+ return cells.filter(cell => cell.bucket.state === "verified" && cell.bucket.value === bucket).length;
50
+ }
51
+ /**
52
+ * Summarise the report.
53
+ * @param rows - Every gate row
54
+ * @param momentCount - Moments on the report's axis
55
+ * @returns The summary block
56
+ */
57
+ export function summarise(rows, momentCount) {
58
+ const cells = rows.flatMap(row => row.moments.filter(cell => cell.legal));
59
+ const governedBySettings = rows.filter(isGoverned).length;
60
+ const declaredOffOnly = rows.filter(isOffOnly).length;
61
+ return {
62
+ gateCount: rows.length,
63
+ momentCount,
64
+ governedBySettings,
65
+ declaredOffOnly,
66
+ notDeclared: rows.length - governedBySettings - declaredOffOnly,
67
+ legalCells: cells.length,
68
+ buckets: {
69
+ A: countBucket(cells, "A"),
70
+ B: countBucket(cells, "B"),
71
+ C: countBucket(cells, "C"),
72
+ D: countBucket(cells, "D"),
73
+ },
74
+ bucketUnknown: cells.filter(cell => cell.bucket.state !== "verified")
75
+ .length,
76
+ declaredWithoutCommand: cells.filter(isDeclaredWithoutCommand).length,
77
+ provedAnyway: cells.filter(isProvedAnyway).length,
78
+ };
79
+ }
80
+ //# sourceMappingURL=gate-report-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-report-summary.js","sourceRoot":"","sources":["../../src/cli/gate-report-summary.ts"],"names":[],"mappings":"AAgBA,2CAA2C;AAC3C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAExD;;;;GAIG;AACH,SAAS,UAAU,CAAC,GAAkB;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAkB;IACnC,OAAO,CACL,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,CACzE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,IAAoB;IAC1C,OAAO,CACL,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAC3D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,IAAoB;IACpD,OAAO,CACL,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,KAAK,KAAK,UAAU;QACvC,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAC1B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,KAAgC,EAAE,MAAc;IACnE,OAAO,KAAK,CAAC,MAAM,CACjB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,CACzE,CAAC,MAAM,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,IAA8B,EAC9B,WAAmB;IAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACtD,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,MAAM;QACtB,WAAW;QACX,kBAAkB;QAClB,eAAe;QACf,WAAW,EAAE,IAAI,CAAC,MAAM,GAAG,kBAAkB,GAAG,eAAe;QAC/D,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,OAAO,EAAE;YACP,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1B,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1B,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1B,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC;SAC3B;QACD,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC;aAClE,MAAM;QACT,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,MAAM;QACrE,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM;KAClD,CAAC;AACJ,CAAC"}