@codyswann/lisa 3.59.1 → 3.60.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.
- package/all/copy-overwrite/scripts/lisa-gates.mjs +225 -22
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +20 -3
- package/dist/cli/gate-report-cells.d.ts +13 -1
- package/dist/cli/gate-report-cells.d.ts.map +1 -1
- package/dist/cli/gate-report-cells.js +41 -2
- package/dist/cli/gate-report-cells.js.map +1 -1
- package/dist/cli/gate-report-registry.d.ts +17 -0
- package/dist/cli/gate-report-registry.d.ts.map +1 -1
- package/dist/cli/gate-report-registry.js.map +1 -1
- package/dist/cli/gate-report-rows.d.ts.map +1 -1
- package/dist/cli/gate-report-rows.js +23 -5
- package/dist/cli/gate-report-rows.js.map +1 -1
- package/dist/cli/gate-report-types.d.ts +9 -2
- package/dist/cli/gate-report-types.d.ts.map +1 -1
- package/dist/cli/gate-report.d.ts.map +1 -1
- package/dist/cli/gate-report.js +6 -2
- package/dist/cli/gate-report.js.map +1 -1
- package/dist/cli/ui-ci-quality-jobs-compute.js +2 -2
- package/dist/cli/ui-ci-quality-jobs-compute.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +7 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +15 -10
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/create-only/.github/required-checks.json +1 -1
- package/expo/create-only/.github/workflows/nightly-e2e-health.yml +1 -1
- package/nestjs/create-only/.github/required-checks.json +1 -1
- package/package.json +1 -1
- package/phaser/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/rails/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
- package/typescript/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
- package/typescript/github-rulesets/quality-checks.json +1 -1
- package/ui/index.html +2 -2
|
@@ -282,6 +282,15 @@ const KNIP = "knip";
|
|
|
282
282
|
* - `shippedAs` names the script a template already ships for that concern,
|
|
283
283
|
* where one exists, so an operator can point `run:` straight at it.
|
|
284
284
|
*
|
|
285
|
+
* `shippedAs` is RESOLVED THROUGH, not merely documented — see `resolveMoment`.
|
|
286
|
+
* Recording the alias and then never reading it (#2916) left the registry
|
|
287
|
+
* knowing, in machine-readable form, that a working prover sat in the
|
|
288
|
+
* consumer's own `package.json`, while every operator surface still resolved to
|
|
289
|
+
* the concern name and failed as `Missing script`. The fallback fires only when
|
|
290
|
+
* the concern-named script is genuinely absent and the alias is genuinely
|
|
291
|
+
* present, so it can never widen what resolves: the concern name stays the
|
|
292
|
+
* gate's identity, its label, and its first choice.
|
|
293
|
+
*
|
|
285
294
|
* The ABSENCE of `declareOnly` is therefore a claim, and
|
|
286
295
|
* `tests/unit/config/gate-default-tasks-resolve.test.ts` enforces it in both
|
|
287
296
|
* directions: a gate without the field must resolve on every npm stack, and a
|
|
@@ -368,13 +377,18 @@ export const REGISTRY = Object.freeze({
|
|
|
368
377
|
task: "test:coverage",
|
|
369
378
|
shippedAs: "test:cov",
|
|
370
379
|
declareOnly:
|
|
371
|
-
"Every npm stack ships `test:cov`, which proves this. The default keeps the concern's name rather than that spelling, so
|
|
380
|
+
"Every npm stack ships `test:cov`, which proves this. The default keeps the concern's name rather than that spelling, so a project without a `test:coverage` script resolves through `test:cov` automatically; add `test:coverage`, or name a `run:` of your own, to take that back.",
|
|
372
381
|
moments: PUSH_ONWARD,
|
|
373
382
|
work: "files measured",
|
|
374
383
|
costly: true,
|
|
375
384
|
},
|
|
376
385
|
"e2e-browser": {
|
|
377
|
-
label: "🎭
|
|
386
|
+
label: "🎭 Browser Journeys",
|
|
387
|
+
// The label used to name the vendor. `contextsFor` emits the union of the
|
|
388
|
+
// current label and everything here, so a ruleset generated during the
|
|
389
|
+
// migration requires both strings and neither side has to remember the
|
|
390
|
+
// rename happened.
|
|
391
|
+
previousLabels: ["🎭 Playwright E2E Tests"],
|
|
378
392
|
summary: "Browser journeys pass end to end.",
|
|
379
393
|
task: "test:e2e",
|
|
380
394
|
declareOnly:
|
|
@@ -384,12 +398,13 @@ export const REGISTRY = Object.freeze({
|
|
|
384
398
|
costly: true,
|
|
385
399
|
},
|
|
386
400
|
"e2e-native": {
|
|
387
|
-
label: "📱
|
|
401
|
+
label: "📱 Native Device Journeys",
|
|
402
|
+
previousLabels: ["📱 Maestro Native E2E"],
|
|
388
403
|
summary: "Native device journeys pass end to end.",
|
|
389
404
|
task: "test:e2e:native",
|
|
390
405
|
shippedAs: "maestro:test",
|
|
391
406
|
declareOnly:
|
|
392
|
-
"Only the expo stack ships a prover, as `maestro:test
|
|
407
|
+
"Only the expo stack ships a prover, as `maestro:test`, which an expo project resolves through automatically. Elsewhere, point `run:` at your own device suite — nothing else proves this.",
|
|
393
408
|
moments: [...PR_ONWARD, CONTINUOUS],
|
|
394
409
|
work: "flows run",
|
|
395
410
|
costly: true,
|
|
@@ -513,12 +528,17 @@ export const REGISTRY = Object.freeze({
|
|
|
513
528
|
costly: true,
|
|
514
529
|
},
|
|
515
530
|
"structural-rules": {
|
|
516
|
-
label: "🔎
|
|
531
|
+
label: "🔎 Structural Rules",
|
|
532
|
+
// The only one of the three whose old context is REQUIRED on this
|
|
533
|
+
// repository's ruleset, so this entry is not decoration: it is what tells
|
|
534
|
+
// a ruleset generator to keep requiring the old string until the rollout
|
|
535
|
+
// says otherwise.
|
|
536
|
+
previousLabels: ["🔎 AST Grep Scan"],
|
|
517
537
|
summary: "Structural rules lint cannot express are respected.",
|
|
518
538
|
task: "lint:structural",
|
|
519
539
|
shippedAs: "sg:scan",
|
|
520
540
|
declareOnly:
|
|
521
|
-
"Every npm stack ships `sg:scan`, which proves this. CI's fallback runs it directly, and the pre-commit hook proves the same property through lint-staged.",
|
|
541
|
+
"Every npm stack ships `sg:scan`, which proves this and which a project without a `lint:structural` script resolves through automatically. CI's fallback runs it directly, and the pre-commit hook proves the same property through lint-staged.",
|
|
522
542
|
// Commit-legal, corrected from push-onward against the evidence:
|
|
523
543
|
// `.lintstagedrc.json` already runs `ast-grep scan` on staged files at
|
|
524
544
|
// commit time. Declaring it push-onward made an enforcement that
|
|
@@ -571,7 +591,7 @@ export const REGISTRY = Object.freeze({
|
|
|
571
591
|
task: "check:dead-code",
|
|
572
592
|
shippedAs: KNIP_CHECK_TASK,
|
|
573
593
|
declareOnly:
|
|
574
|
-
"Every npm stack ships `knip:check`, which proves this. CI's fallback runs it directly (and falls back again to the older `knip`), so the property is proved today whether or not the concern-named script exists.",
|
|
594
|
+
"Every npm stack ships `knip:check`, which proves this and which a project without the concern-named script resolves through automatically. CI's fallback runs it directly (and falls back again to the older `knip`), so the property is proved today whether or not the concern-named script exists.",
|
|
575
595
|
moments: PUSH_ONWARD,
|
|
576
596
|
},
|
|
577
597
|
"credential-leakage": {
|
|
@@ -608,7 +628,7 @@ export const REGISTRY = Object.freeze({
|
|
|
608
628
|
task: "security:dast",
|
|
609
629
|
shippedAs: "security:zap",
|
|
610
630
|
declareOnly:
|
|
611
|
-
"Only the expo and nestjs stacks ship a prover, as `security:zap
|
|
631
|
+
"Only the expo and nestjs stacks ship a prover, as `security:zap`, which those projects resolve through automatically. Elsewhere, point `run:` at whatever scans your running application — nothing else proves this.",
|
|
612
632
|
moments: DEPLOY_ONLY,
|
|
613
633
|
work: "URLs scanned",
|
|
614
634
|
},
|
|
@@ -633,7 +653,7 @@ export const REGISTRY = Object.freeze({
|
|
|
633
653
|
task: "perf:check",
|
|
634
654
|
shippedAs: "lighthouse:check",
|
|
635
655
|
declareOnly:
|
|
636
|
-
"Only the expo stack ships a prover, as `lighthouse:check
|
|
656
|
+
"Only the expo stack ships a prover, as `lighthouse:check`; an expo project resolves through it automatically and CI's fallback runs it directly. Elsewhere, point `run:` at whatever measures your pages.",
|
|
637
657
|
// Widened from DEPLOY_ONLY. The measurement was already running in CI on
|
|
638
658
|
// every consumer — through a standalone `lighthouse.yml`, outside the
|
|
639
659
|
// registry, with no level and therefore no way to declare it `off`. A
|
|
@@ -653,7 +673,7 @@ export const REGISTRY = Object.freeze({
|
|
|
653
673
|
task: "perf:load",
|
|
654
674
|
shippedAs: "k6:load",
|
|
655
675
|
declareOnly:
|
|
656
|
-
"Only the nestjs stack ships a prover, and it ships several tiers — `k6:smoke`, `k6:load`, `k6:soak`, `k6:stress`, `k6:spike`. Which tier is the budget is a project decision, so point `run:` at
|
|
676
|
+
"Only the nestjs stack ships a prover, and it ships several tiers — `k6:smoke`, `k6:load`, `k6:soak`, `k6:stress`, `k6:spike`. Which tier is the budget is a project decision: absent a `run:`, this resolves through `k6:load` because that is the tier whose name matches the concern, so point `run:` at another tier to mean a different one.",
|
|
657
677
|
moments: DEPLOY_ONLY,
|
|
658
678
|
work: "requests issued",
|
|
659
679
|
costly: true,
|
|
@@ -2074,6 +2094,60 @@ export function readGates(cwd = process.cwd()) {
|
|
|
2074
2094
|
return { runner, gates, policy: config.policy ?? {}, config };
|
|
2075
2095
|
}
|
|
2076
2096
|
|
|
2097
|
+
/**
|
|
2098
|
+
* The `scripts` block of a project's `package.json`, or `null` when unknown.
|
|
2099
|
+
*
|
|
2100
|
+
* `null` is a THIRD answer, distinct from `{}`, and the distinction is the
|
|
2101
|
+
* whole safety of the `shippedAs` fallback. `{}` says "this project ships no
|
|
2102
|
+
* scripts", which is a fact the resolver may act on; `null` says "nobody
|
|
2103
|
+
* knows", which it may not. Collapsing the two would let an absent or
|
|
2104
|
+
* unparseable manifest read as "the concern-named script is missing" and send
|
|
2105
|
+
* every aliased gate at a vendor script that might not be there either.
|
|
2106
|
+
* @param {string} [cwd] Project root.
|
|
2107
|
+
* @returns {Record<string, string>|null} The scripts, or null when unknown.
|
|
2108
|
+
*/
|
|
2109
|
+
export function projectScripts(cwd = process.cwd()) {
|
|
2110
|
+
const path = join(cwd, "package.json");
|
|
2111
|
+
if (!existsSync(path)) return null;
|
|
2112
|
+
try {
|
|
2113
|
+
const scripts = JSON.parse(readFileSync(path, "utf8"))?.scripts;
|
|
2114
|
+
return scripts && typeof scripts === "object" ? scripts : {};
|
|
2115
|
+
} catch {
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
/**
|
|
2121
|
+
* Whether a registry default should stand aside for the script this project
|
|
2122
|
+
* actually ships, and which script that is.
|
|
2123
|
+
*
|
|
2124
|
+
* Three conditions, all required, and each one closes a different way of
|
|
2125
|
+
* resolving more than the registry knows:
|
|
2126
|
+
*
|
|
2127
|
+
* - the project declared no prover of its own, because `run:` is the project
|
|
2128
|
+
* saying what proves this property here and nothing outranks it;
|
|
2129
|
+
* - the concern-named default is ABSENT from this project, so the alias is
|
|
2130
|
+
* standing in for nothing rather than displacing a working script;
|
|
2131
|
+
* - the alias is PRESENT, so the substitution names a command that exists.
|
|
2132
|
+
*
|
|
2133
|
+
* With `scripts` unknown, none of the last two can be established and the
|
|
2134
|
+
* answer is no.
|
|
2135
|
+
* @param {object} options Inputs.
|
|
2136
|
+
* @param {string|null} options.declared The project's own `run:`, if any.
|
|
2137
|
+
* @param {string|null} options.registryTask The registry default for here.
|
|
2138
|
+
* @param {string|null} options.shippedAs The alias the registry records.
|
|
2139
|
+
* @param {Record<string, string>|null} options.scripts The project's scripts.
|
|
2140
|
+
* @returns {{from: string, to: string}|null} The substitution, or null.
|
|
2141
|
+
*/
|
|
2142
|
+
function aliasFor({ declared, registryTask, shippedAs, scripts }) {
|
|
2143
|
+
if (declared !== null && declared !== undefined) return null;
|
|
2144
|
+
if (!registryTask || !shippedAs) return null;
|
|
2145
|
+
if (scripts === null || typeof scripts !== "object") return null;
|
|
2146
|
+
if (Object.hasOwn(scripts, registryTask)) return null;
|
|
2147
|
+
if (!Object.hasOwn(scripts, shippedAs)) return null;
|
|
2148
|
+
return { from: registryTask, to: shippedAs };
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2077
2151
|
/**
|
|
2078
2152
|
* The project's package.json scripts, for deciding what a seed may declare.
|
|
2079
2153
|
*
|
|
@@ -2465,13 +2539,19 @@ export function auditConfigKeys(config) {
|
|
|
2465
2539
|
* consumer that RUNS these entries must not see a gate the project turned
|
|
2466
2540
|
* off. Callers that need to tell "declared off" from "never declared" — the
|
|
2467
2541
|
* CI façade does — pass true and branch on the level themselves.
|
|
2468
|
-
* @
|
|
2542
|
+
* @param {Record<string, string>|null} [options.scripts] The project's
|
|
2543
|
+
* `package.json` scripts, from `projectScripts`. Omitted or `null` means
|
|
2544
|
+
* UNKNOWN, and an unknown manifest resolves exactly as it did before this
|
|
2545
|
+
* option existed — a caller that has not been taught to read the manifest
|
|
2546
|
+
* must not have its answers changed by silence.
|
|
2547
|
+
* @returns {Array<{id: string, level: string, mode: string, awaits: string|null, task: string|null, command: string|null, label: string, work: string|null, alias: {from: string, to: string}|null, evidence: {proof: string[], no_work: string[], on_hollow: string, wait_minutes: number|null, on_timeout: string}|null}>} Resolved provers, sorted by gate id.
|
|
2469
2548
|
*/
|
|
2470
2549
|
export function resolveMoment({
|
|
2471
2550
|
gates,
|
|
2472
2551
|
moment,
|
|
2473
2552
|
runner = DEFAULT_RUNNER,
|
|
2474
2553
|
includeOff = false,
|
|
2554
|
+
scripts = null,
|
|
2475
2555
|
}) {
|
|
2476
2556
|
// The same guard as `readGates`, at the site that BUILDS the command. A
|
|
2477
2557
|
// destructuring default fires only on `undefined`, so a caller passing the
|
|
@@ -2522,6 +2602,7 @@ export function resolveMoment({
|
|
|
2522
2602
|
command: null,
|
|
2523
2603
|
label: REGISTRY[id]?.label ?? id,
|
|
2524
2604
|
work: null,
|
|
2605
|
+
alias: null,
|
|
2525
2606
|
evidence: null,
|
|
2526
2607
|
mayRewrite: false,
|
|
2527
2608
|
costly: false,
|
|
@@ -2538,12 +2619,20 @@ export function resolveMoment({
|
|
|
2538
2619
|
// `task` because a gate whose default prover differs by moment has no
|
|
2539
2620
|
// single default — see `traceability`, where the pull-request prover reads
|
|
2540
2621
|
// a pull request that does not exist yet at push.
|
|
2541
|
-
const
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2622
|
+
const declared = entry.run ?? gate.run ?? null;
|
|
2623
|
+
const registryTask =
|
|
2624
|
+
definition?.taskAt?.[momentFamily(moment)] ?? definition?.task ?? null;
|
|
2625
|
+
// The fifth source, and the only one that reads the project's disk. It is
|
|
2626
|
+
// deliberately BELOW all four: `shippedAs` says what the template ships,
|
|
2627
|
+
// which is a weaker claim than what this project declared, and it may only
|
|
2628
|
+
// ever stand in for a registry default that resolves to nothing here.
|
|
2629
|
+
const alias = aliasFor({
|
|
2630
|
+
declared,
|
|
2631
|
+
registryTask,
|
|
2632
|
+
shippedAs: definition?.shippedAs ?? null,
|
|
2633
|
+
scripts,
|
|
2634
|
+
});
|
|
2635
|
+
const task = declared ?? alias?.to ?? registryTask;
|
|
2547
2636
|
const intercepts = Object.hasOwn(INTERCEPTORS, id);
|
|
2548
2637
|
|
|
2549
2638
|
resolved.push({
|
|
@@ -2555,6 +2644,7 @@ export function resolveMoment({
|
|
|
2555
2644
|
command: entry.await || intercepts || !task ? null : `${runner} ${task}`,
|
|
2556
2645
|
label: definition?.label ?? id,
|
|
2557
2646
|
work: definition?.work ?? null,
|
|
2647
|
+
alias: entry.await || intercepts ? null : alias,
|
|
2558
2648
|
evidence: entry.await ? mergeEvidence(entry.evidence) : null,
|
|
2559
2649
|
mayRewrite: definition?.mayRewrite === true,
|
|
2560
2650
|
costly: definition?.costly === true,
|
|
@@ -2649,10 +2739,23 @@ export function contextsFor(gates, options = {}) {
|
|
|
2649
2739
|
.filter(gate => gate.level === "required")
|
|
2650
2740
|
// An awaited signal posts under its own name; a run job posts under the
|
|
2651
2741
|
// calling workflow's.
|
|
2652
|
-
.
|
|
2653
|
-
gate.mode === "await"
|
|
2654
|
-
|
|
2742
|
+
.flatMap(gate => {
|
|
2743
|
+
if (gate.mode === "await") return [gate.awaits];
|
|
2744
|
+
// The gate's OWN record of what it used to be called, unioned in
|
|
2745
|
+
// automatically. This was a `--previous` flag the caller had to
|
|
2746
|
+
// remember, which meant nothing knew a rename was in flight and a
|
|
2747
|
+
// consumer who forgot the flag got a hard cutover. A rename is now
|
|
2748
|
+
// DECLARED once, in the registry, and every derivation sees it.
|
|
2749
|
+
const former = REGISTRY[gate.id]?.previousLabels ?? [];
|
|
2750
|
+
return [
|
|
2751
|
+
`${workflowName} / ${gate.label}`,
|
|
2752
|
+
...former.map(label => `${workflowName} / ${label}`),
|
|
2753
|
+
];
|
|
2754
|
+
});
|
|
2655
2755
|
|
|
2756
|
+
// Still honoured, and still additive. The flag now answers a different
|
|
2757
|
+
// question from the registry field: the field records a rename Lisa shipped,
|
|
2758
|
+
// the flag names a string some particular ruleset happens to carry.
|
|
2656
2759
|
for (const label of previousLabels) {
|
|
2657
2760
|
contexts.push(`${workflowName} / ${label}`);
|
|
2658
2761
|
}
|
|
@@ -2739,6 +2842,90 @@ function distance(a, b) {
|
|
|
2739
2842
|
return previous[b.length];
|
|
2740
2843
|
}
|
|
2741
2844
|
|
|
2845
|
+
/**
|
|
2846
|
+
* Advisory findings about gates whose prover this project does not ship.
|
|
2847
|
+
*
|
|
2848
|
+
* The gap this closes: `validate` printed `configuration is valid`, exit 0,
|
|
2849
|
+
* for a gate resolving to a script the project has never had. That is the
|
|
2850
|
+
* declared-but-uncallable defect applied to config validation itself — the
|
|
2851
|
+
* operator's only remaining signal was a red CI job weeks later reading
|
|
2852
|
+
* `Missing script`.
|
|
2853
|
+
*
|
|
2854
|
+
* ADVISORY, deliberately. Turning an unresolvable gate into a blocking
|
|
2855
|
+
* validation failure would red-wall every consumer the moment they upgrade,
|
|
2856
|
+
* for declarations that were legal when they wrote them. Saying it out loud
|
|
2857
|
+
* costs nothing and is the whole ask.
|
|
2858
|
+
*
|
|
2859
|
+
* Silent when the manifest is unknown: `null` scripts means nobody read a
|
|
2860
|
+
* `package.json`, and reporting "this project has no such script" from a file
|
|
2861
|
+
* nobody read would be the same fabrication one level down.
|
|
2862
|
+
* @param {object} options Inputs.
|
|
2863
|
+
* @param {object} options.gates The gates block.
|
|
2864
|
+
* @param {string} options.runner The task-runner prefix.
|
|
2865
|
+
* @param {Record<string, string>|null} options.scripts The project's scripts.
|
|
2866
|
+
* @returns {string[]} Advisory messages, de-duplicated, in gate order.
|
|
2867
|
+
*/
|
|
2868
|
+
export function auditProvers({ gates, runner, scripts }) {
|
|
2869
|
+
if (scripts === null || typeof scripts !== "object") return [];
|
|
2870
|
+
const moments = new Set(
|
|
2871
|
+
Object.values(gates ?? {})
|
|
2872
|
+
.filter(gate => gate !== null && typeof gate === "object")
|
|
2873
|
+
.flatMap(gate => Object.keys(gate))
|
|
2874
|
+
.filter(key => isMoment(key))
|
|
2875
|
+
);
|
|
2876
|
+
const seen = new Set();
|
|
2877
|
+
for (const moment of [...moments].sort((a, b) => a.localeCompare(b))) {
|
|
2878
|
+
let resolved;
|
|
2879
|
+
try {
|
|
2880
|
+
resolved = resolveMoment({ gates, moment, runner, scripts });
|
|
2881
|
+
} catch {
|
|
2882
|
+
// An unresolvable moment is already a BLOCKING problem from
|
|
2883
|
+
// `validateGates`, reported with a better message than this one could
|
|
2884
|
+
// give. Advisory work never competes with it.
|
|
2885
|
+
continue;
|
|
2886
|
+
}
|
|
2887
|
+
for (const gate of resolved) {
|
|
2888
|
+
const message = proverAdvice(gate, moment, runner, scripts);
|
|
2889
|
+
if (message) seen.add(message);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
return [...seen];
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
/**
|
|
2896
|
+
* What to tell an operator about one resolved gate's prover, if anything.
|
|
2897
|
+
* @param {object} gate One entry from `resolveMoment`.
|
|
2898
|
+
* @param {string} moment The moment it was resolved at.
|
|
2899
|
+
* @param {string} runner The task-runner prefix.
|
|
2900
|
+
* @param {Record<string, string>} scripts The project's scripts.
|
|
2901
|
+
* @returns {string|null} The advisory, or null when there is nothing to say.
|
|
2902
|
+
*/
|
|
2903
|
+
function proverAdvice(gate, moment, runner, scripts) {
|
|
2904
|
+
if (gate.mode !== "run" || !gate.task) return null;
|
|
2905
|
+
const where = `gates."${gate.id}"."${moment}"`;
|
|
2906
|
+
if (gate.alias) {
|
|
2907
|
+
return (
|
|
2908
|
+
`${where} has no "${gate.alias.from}" script in this project, so it ` +
|
|
2909
|
+
`runs "${runner} ${gate.alias.to}" — the prover this project does ` +
|
|
2910
|
+
`ship for that property. Add "run": "${gate.alias.to}" to say so ` +
|
|
2911
|
+
`explicitly, or add a "${gate.alias.from}" script to take it back.`
|
|
2912
|
+
);
|
|
2913
|
+
}
|
|
2914
|
+
if (Object.hasOwn(scripts, gate.task)) return null;
|
|
2915
|
+
const shippedAs = REGISTRY[gate.id]?.shippedAs;
|
|
2916
|
+
const elsewhere =
|
|
2917
|
+
shippedAs && shippedAs !== gate.task
|
|
2918
|
+
? ` A Lisa template ships a prover for this property as ` +
|
|
2919
|
+
`"${shippedAs}", which this project does not have either.`
|
|
2920
|
+
: "";
|
|
2921
|
+
return (
|
|
2922
|
+
`${where} runs "${runner} ${gate.task}", and this project has no ` +
|
|
2923
|
+
`"${gate.task}" script. Nothing will prove it, so declaring it here ` +
|
|
2924
|
+
`guarantees a red gate rather than a guarantee.${elsewhere} Point ` +
|
|
2925
|
+
`"run" at a prover, or declare the gate "off" to say it is not proved here.`
|
|
2926
|
+
);
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2742
2929
|
/**
|
|
2743
2930
|
* CLI entry point.
|
|
2744
2931
|
*/
|
|
@@ -2749,10 +2936,17 @@ function main() {
|
|
|
2749
2936
|
return hit ? hit.slice(name.length + 3) : null;
|
|
2750
2937
|
};
|
|
2751
2938
|
const { runner, gates, policy, config } = readGates();
|
|
2939
|
+
// Read once, here, so every subcommand answers about the same project. The
|
|
2940
|
+
// resolver is handed the result rather than reading the disk itself, which
|
|
2941
|
+
// keeps it a pure function of its inputs.
|
|
2942
|
+
const scripts = projectScripts();
|
|
2752
2943
|
|
|
2753
2944
|
if (command === "validate") {
|
|
2754
2945
|
const blocking = [...validateGates(gates), ...validatePolicy(policy)];
|
|
2755
|
-
const advisory =
|
|
2946
|
+
const advisory = [
|
|
2947
|
+
...auditConfigKeys(config).map(finding => finding.message),
|
|
2948
|
+
...auditProvers({ gates, runner, scripts }),
|
|
2949
|
+
];
|
|
2756
2950
|
for (const problem of [...blocking, ...advisory]) {
|
|
2757
2951
|
console.error(` ${problem}`);
|
|
2758
2952
|
}
|
|
@@ -2779,6 +2973,7 @@ function main() {
|
|
|
2779
2973
|
moment,
|
|
2780
2974
|
runner,
|
|
2781
2975
|
includeOff: rest.includes("--include-off"),
|
|
2976
|
+
scripts,
|
|
2782
2977
|
});
|
|
2783
2978
|
if (rest.includes("--json")) {
|
|
2784
2979
|
console.log(JSON.stringify(resolved, null, 2));
|
|
@@ -2797,7 +2992,15 @@ function main() {
|
|
|
2797
2992
|
: gate.mode === "intercept"
|
|
2798
2993
|
? "(intercepted by Lisa)"
|
|
2799
2994
|
: (gate.command ?? "(NO PROVER — nothing runs this gate)");
|
|
2800
|
-
|
|
2995
|
+
// Two scripts can back one gate once `shippedAs` resolves, so a listing
|
|
2996
|
+
// that printed only the winner would leave the reader unable to tell a
|
|
2997
|
+
// project that declared this prover from one that inherited it.
|
|
2998
|
+
const alias = gate.alias
|
|
2999
|
+
? ` (no "${gate.alias.from}" script here; using "${gate.alias.to}")`
|
|
3000
|
+
: "";
|
|
3001
|
+
console.log(
|
|
3002
|
+
`${gate.level.padEnd(9)} ${gate.id.padEnd(28)} ${how}${alias}`
|
|
3003
|
+
);
|
|
2801
3004
|
}
|
|
2802
3005
|
return;
|
|
2803
3006
|
}
|
|
@@ -54,7 +54,7 @@ import { join } from "node:path";
|
|
|
54
54
|
|
|
55
55
|
import { diagnoseFailure } from "./lib/gate-failure-diagnosis.mjs";
|
|
56
56
|
import { invokedAsScript } from "./lib/invoked-as-script.mjs";
|
|
57
|
-
import { readGates, resolveMoment } from "./lisa-gates.mjs";
|
|
57
|
+
import { projectScripts, readGates, resolveMoment } from "./lisa-gates.mjs";
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* What this process tells its caller. The hooks branch on every value.
|
|
@@ -241,6 +241,11 @@ function skipReason(gate) {
|
|
|
241
241
|
|
|
242
242
|
/**
|
|
243
243
|
* One aligned line per gate, so a transcript can be read at a glance.
|
|
244
|
+
*
|
|
245
|
+
* A gate resolved through `shippedAs` says so on its own line, naming both
|
|
246
|
+
* scripts. Two scripts can now back one gate, so "what proved this" stops
|
|
247
|
+
* being answerable from the gate id alone — and a reader who has to open the
|
|
248
|
+
* registry to find out is back where #2916 started.
|
|
244
249
|
* @param {string} state A `STATE` value.
|
|
245
250
|
* @param {GateOutcome} gate The resolved gate.
|
|
246
251
|
* @param {string} detail Command, reason, or failure note.
|
|
@@ -249,7 +254,10 @@ function skipReason(gate) {
|
|
|
249
254
|
function formatLine(state, gate, detail) {
|
|
250
255
|
const token = `${state.toUpperCase()}`.padEnd(STATE_WIDTH);
|
|
251
256
|
const id = gate.id.padEnd(ID_WIDTH);
|
|
252
|
-
|
|
257
|
+
const alias = gate.alias
|
|
258
|
+
? ` (no "${gate.alias.from}" script here; this project ships "${gate.alias.to}")`
|
|
259
|
+
: "";
|
|
260
|
+
return ` ${token}${gate.level.padEnd(9)}${id}${detail}${alias}`;
|
|
253
261
|
}
|
|
254
262
|
|
|
255
263
|
/**
|
|
@@ -534,6 +542,9 @@ function verdictFor(gate, { proved, blockedBy, exec, siblings }) {
|
|
|
534
542
|
* @param {string} [options.runner] Task-runner prefix, e.g. `bun run`.
|
|
535
543
|
* @param {function(string, GateOutcome): (number|null)} options.exec Executor.
|
|
536
544
|
* @param {function(string): void} [options.out] Line sink; defaults to stdout.
|
|
545
|
+
* @param {Record<string, string>|null} [options.scripts] The project's package
|
|
546
|
+
* scripts, from `projectScripts`. `null` means unknown, and an unknown
|
|
547
|
+
* manifest resolves exactly as it did before `shippedAs` was consulted.
|
|
537
548
|
* @returns {GateRun} What every declared gate at this moment produced.
|
|
538
549
|
*/
|
|
539
550
|
export function runGates({
|
|
@@ -542,8 +553,9 @@ export function runGates({
|
|
|
542
553
|
runner = "npm run",
|
|
543
554
|
exec,
|
|
544
555
|
out = line => console.log(line),
|
|
556
|
+
scripts = null,
|
|
545
557
|
}) {
|
|
546
|
-
const resolved = resolveMoment({ gates, moment, runner });
|
|
558
|
+
const resolved = resolveMoment({ gates, moment, runner, scripts });
|
|
547
559
|
const results = [];
|
|
548
560
|
// The id of the first required gate to go unproved, not merely a boolean:
|
|
549
561
|
// every gate queued behind it has to be able to say WHAT stopped it, or its
|
|
@@ -918,6 +930,11 @@ function main() {
|
|
|
918
930
|
moment,
|
|
919
931
|
runner: config.runner,
|
|
920
932
|
exec: spawnExec,
|
|
933
|
+
// The manifest is read HERE and handed down, rather than read inside the
|
|
934
|
+
// resolver, so that `runGates` stays a pure function of its inputs and
|
|
935
|
+
// every test above can state what this project ships instead of writing a
|
|
936
|
+
// package.json to disk to find out.
|
|
937
|
+
scripts: projectScripts(),
|
|
921
938
|
});
|
|
922
939
|
// A gates block that declares nothing at this moment is a deliberate
|
|
923
940
|
// statement, not an unmigrated project: the registry governs the moment and
|
|
@@ -60,16 +60,27 @@ export interface CellContext {
|
|
|
60
60
|
*/
|
|
61
61
|
export declare function gateLevelRun(gates: Record<string, unknown>, id: string): string | null;
|
|
62
62
|
/**
|
|
63
|
-
* Which of the
|
|
63
|
+
* Which of the five sources supplies this pair's task.
|
|
64
64
|
*
|
|
65
65
|
* Named rather than merely resolved: a per-moment `run` and a gate-level `run`
|
|
66
66
|
* produce identical commands and mean different things, and a registry `taskAt`
|
|
67
67
|
* swap ships to every project while a project `run` does not.
|
|
68
|
+
*
|
|
69
|
+
* This ladder is a SECOND implementation of the one in `resolveMoment`, which
|
|
70
|
+
* returns only the winner's task and cannot say which rung it came from. The
|
|
71
|
+
* duplication is deliberate and its cost is real: a rung added to one and not
|
|
72
|
+
* the other makes this report describe a command the runner will not run. When
|
|
73
|
+
* the fifth rung landed (#2916), a report left un-updated would have printed
|
|
74
|
+
* `security:dast`, `commandExists: false`, and bucket C for a gate that
|
|
75
|
+
* actually runs `security:zap` and passes.
|
|
68
76
|
* @param options - Resolution inputs
|
|
69
77
|
* @param options.entry - The raw per-moment entry
|
|
70
78
|
* @param options.gateRun - A gate-level project `run`
|
|
71
79
|
* @param options.definition - The registry gate
|
|
72
80
|
* @param options.family - The moment's family
|
|
81
|
+
* @param options.scripts - The project's `package.json` scripts, or null when
|
|
82
|
+
* unreadable. `null` suppresses the `shippedAs` rung entirely: an unknown
|
|
83
|
+
* manifest cannot establish that the concern-named script is absent.
|
|
73
84
|
* @returns The winning source and its task
|
|
74
85
|
*/
|
|
75
86
|
export declare function resolveProvenance(options: {
|
|
@@ -77,6 +88,7 @@ export declare function resolveProvenance(options: {
|
|
|
77
88
|
gateRun: string | null;
|
|
78
89
|
definition: RegistryGate | undefined;
|
|
79
90
|
family: string;
|
|
91
|
+
scripts?: Readonly<Record<string, string>> | null;
|
|
80
92
|
}): {
|
|
81
93
|
task: string | null;
|
|
82
94
|
provenance: TaskProvenance;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-report-cells.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-cells.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,KAAK,EACV,MAAM,EAEN,gBAAgB,EAChB,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACf,MAAM,wBAAwB,CAAC;AAWhC,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC;IAC5D,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1D,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,CACpB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GAAG,IAAI,KAC3B,OAAO,CAAC,UAAU,CAAC,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAAG,IAAI,KACtB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7B;AA2BD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,IAAI,CAKf;AAED
|
|
1
|
+
{"version":3,"file":"gate-report-cells.d.ts","sourceRoot":"","sources":["../../src/cli/gate-report-cells.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,20 +41,31 @@ export function gateLevelRun(gates, id) {
|
|
|
41
41
|
return typeof run === "string" ? run : null;
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* Which of the
|
|
44
|
+
* Which of the five sources supplies this pair's task.
|
|
45
45
|
*
|
|
46
46
|
* Named rather than merely resolved: a per-moment `run` and a gate-level `run`
|
|
47
47
|
* produce identical commands and mean different things, and a registry `taskAt`
|
|
48
48
|
* swap ships to every project while a project `run` does not.
|
|
49
|
+
*
|
|
50
|
+
* This ladder is a SECOND implementation of the one in `resolveMoment`, which
|
|
51
|
+
* returns only the winner's task and cannot say which rung it came from. The
|
|
52
|
+
* duplication is deliberate and its cost is real: a rung added to one and not
|
|
53
|
+
* the other makes this report describe a command the runner will not run. When
|
|
54
|
+
* the fifth rung landed (#2916), a report left un-updated would have printed
|
|
55
|
+
* `security:dast`, `commandExists: false`, and bucket C for a gate that
|
|
56
|
+
* actually runs `security:zap` and passes.
|
|
49
57
|
* @param options - Resolution inputs
|
|
50
58
|
* @param options.entry - The raw per-moment entry
|
|
51
59
|
* @param options.gateRun - A gate-level project `run`
|
|
52
60
|
* @param options.definition - The registry gate
|
|
53
61
|
* @param options.family - The moment's family
|
|
62
|
+
* @param options.scripts - The project's `package.json` scripts, or null when
|
|
63
|
+
* unreadable. `null` suppresses the `shippedAs` rung entirely: an unknown
|
|
64
|
+
* manifest cannot establish that the concern-named script is absent.
|
|
54
65
|
* @returns The winning source and its task
|
|
55
66
|
*/
|
|
56
67
|
export function resolveProvenance(options) {
|
|
57
|
-
const { entry, gateRun, definition, family } = options;
|
|
68
|
+
const { entry, gateRun, definition, family, scripts = null } = options;
|
|
58
69
|
const momentRun = entry?.run;
|
|
59
70
|
if (typeof momentRun === "string") {
|
|
60
71
|
return { task: momentRun, provenance: "moment-run" };
|
|
@@ -62,6 +73,11 @@ export function resolveProvenance(options) {
|
|
|
62
73
|
if (gateRun !== null)
|
|
63
74
|
return { task: gateRun, provenance: "gate-run" };
|
|
64
75
|
const swap = definition?.taskAt?.[family];
|
|
76
|
+
const registryTask = typeof swap === "string" ? swap : definition?.task;
|
|
77
|
+
const shipped = shippedAsTask(definition, registryTask, scripts);
|
|
78
|
+
if (shipped !== null) {
|
|
79
|
+
return { task: shipped, provenance: "registry-shipped-as" };
|
|
80
|
+
}
|
|
65
81
|
if (typeof swap === "string") {
|
|
66
82
|
return { task: swap, provenance: "registry-task-at" };
|
|
67
83
|
}
|
|
@@ -70,6 +86,28 @@ export function resolveProvenance(options) {
|
|
|
70
86
|
}
|
|
71
87
|
return { task: null, provenance: "none" };
|
|
72
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The alias that stands in for a registry default this project cannot run.
|
|
91
|
+
*
|
|
92
|
+
* The same three conditions `aliasFor` applies in `lisa-gates.mjs`, and they
|
|
93
|
+
* have to stay the same three: the default is absent here, the alias is
|
|
94
|
+
* present here, and the manifest was actually read.
|
|
95
|
+
* @param definition - The registry gate
|
|
96
|
+
* @param registryTask - The registry default that would otherwise win
|
|
97
|
+
* @param scripts - The project's scripts, or null when unreadable
|
|
98
|
+
* @returns The alias to run, or null when the default stands
|
|
99
|
+
*/
|
|
100
|
+
function shippedAsTask(definition, registryTask, scripts) {
|
|
101
|
+
const alias = definition?.shippedAs;
|
|
102
|
+
if (typeof alias !== "string" || typeof registryTask !== "string") {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
if (scripts === null)
|
|
106
|
+
return null;
|
|
107
|
+
if (Object.hasOwn(scripts, registryTask))
|
|
108
|
+
return null;
|
|
109
|
+
return Object.hasOwn(scripts, alias) ? alias : null;
|
|
110
|
+
}
|
|
73
111
|
/**
|
|
74
112
|
* Whether `package.json` defines the task the pair resolves to.
|
|
75
113
|
* @param scripts - The scripts block, or null when unreadable
|
|
@@ -198,6 +236,7 @@ export function buildCell(context, momentContext, id, qualityJob) {
|
|
|
198
236
|
gateRun,
|
|
199
237
|
definition,
|
|
200
238
|
family,
|
|
239
|
+
scripts,
|
|
201
240
|
});
|
|
202
241
|
const hit = resolved?.get(id);
|
|
203
242
|
const declaration = declarationOf(entry, resolved, failure, id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-report-cells.js","sourceRoot":"","sources":["../../src/cli/gate-report-cells.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,YAAY,EAAqB,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAahE,gFAAgF;AAChF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAExD,+DAA+D;AAC/D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3D,wEAAwE;AACxE,MAAM,UAAU,GAAqB,cAAc,CAAC;AAmDpD,oEAAoE;AACpE,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAEzC;;;;;;GAMG;AACH,SAAS,QAAQ,CACf,KAA8B,EAC9B,EAAU,EACV,MAAc;IAEd,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,GAAG,GAAI,IAAgC,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,GAA8B,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,KAA8B,EAC9B,EAAU;IAEV,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,GAAG,GAAI,IAAgC,CAAC,GAAG,CAAC;IAClD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"gate-report-cells.js","sourceRoot":"","sources":["../../src/cli/gate-report-cells.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,17 @@ export interface ResolvedGate {
|
|
|
22
22
|
readonly task: string | null;
|
|
23
23
|
readonly command: string | null;
|
|
24
24
|
readonly label: string;
|
|
25
|
+
/**
|
|
26
|
+
* The `shippedAs` substitution that produced `task`, or null.
|
|
27
|
+
*
|
|
28
|
+
* Non-null only when the concern-named default resolves to no script in this
|
|
29
|
+
* project and the template's own prover does. Two scripts can back one gate,
|
|
30
|
+
* so a caller reporting what ran has to be able to name both.
|
|
31
|
+
*/
|
|
32
|
+
readonly alias?: {
|
|
33
|
+
readonly from: string;
|
|
34
|
+
readonly to: string;
|
|
35
|
+
} | null;
|
|
25
36
|
}
|
|
26
37
|
/** One `skip_jobs` token's migration. */
|
|
27
38
|
export interface SkipJobResolution {
|
|
@@ -50,6 +61,12 @@ export interface GateRegistryModule {
|
|
|
50
61
|
moment: string;
|
|
51
62
|
runner?: string;
|
|
52
63
|
includeOff?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* The project's `package.json` scripts. Omitted or `null` means UNKNOWN,
|
|
66
|
+
* and an unknown manifest resolves exactly as it did before `shippedAs`
|
|
67
|
+
* was consulted — silence must not change an answer.
|
|
68
|
+
*/
|
|
69
|
+
scripts?: Readonly<Record<string, string>> | null;
|
|
53
70
|
}) => ResolvedGate[];
|
|
54
71
|
readonly contextsFor: (gates: Record<string, unknown>, options?: {
|
|
55
72
|
moment?: string;
|