@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.
Files changed (84) hide show
  1. package/all/copy-overwrite/scripts/lisa-gates.mjs +225 -22
  2. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +20 -3
  3. package/dist/cli/gate-report-cells.d.ts +13 -1
  4. package/dist/cli/gate-report-cells.d.ts.map +1 -1
  5. package/dist/cli/gate-report-cells.js +41 -2
  6. package/dist/cli/gate-report-cells.js.map +1 -1
  7. package/dist/cli/gate-report-registry.d.ts +17 -0
  8. package/dist/cli/gate-report-registry.d.ts.map +1 -1
  9. package/dist/cli/gate-report-registry.js.map +1 -1
  10. package/dist/cli/gate-report-rows.d.ts.map +1 -1
  11. package/dist/cli/gate-report-rows.js +23 -5
  12. package/dist/cli/gate-report-rows.js.map +1 -1
  13. package/dist/cli/gate-report-types.d.ts +9 -2
  14. package/dist/cli/gate-report-types.d.ts.map +1 -1
  15. package/dist/cli/gate-report.d.ts.map +1 -1
  16. package/dist/cli/gate-report.js +6 -2
  17. package/dist/cli/gate-report.js.map +1 -1
  18. package/dist/cli/ui-ci-quality-jobs-compute.js +2 -2
  19. package/dist/cli/ui-ci-quality-jobs-compute.js.map +1 -1
  20. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  21. package/dist/core/lisa-owned-hash-ledger.js +7 -0
  22. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  23. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  24. package/dist/core/upstream-evidence-manifest.js +15 -10
  25. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  26. package/expo/create-only/.github/required-checks.json +1 -1
  27. package/expo/create-only/.github/workflows/nightly-e2e-health.yml +1 -1
  28. package/nestjs/create-only/.github/required-checks.json +1 -1
  29. package/package.json +1 -1
  30. package/phaser/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
  31. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-agy/plugin.json +1 -1
  34. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  37. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-expo-agy/plugin.json +1 -1
  44. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  48. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  49. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  54. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  59. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  64. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-rails-agy/plugin.json +1 -1
  69. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  74. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  79. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  81. package/rails/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
  82. package/typescript/copy-overwrite/ast-grep/rule-tests/.gitkeep +1 -1
  83. package/typescript/github-rulesets/quality-checks.json +1 -1
  84. 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 declaring this gate means pointing `run:` at `test:cov` or adding a `test:coverage` script that calls it.",
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: "🎭 Playwright E2E Tests",
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: "📱 Maestro Native E2E",
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`. Elsewhere, point `run:` at your own device suite.",
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: "🔎 AST Grep Scan",
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`. Elsewhere, point `run:` at whatever scans your running application.",
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`, and CI's fallback runs it directly. Elsewhere, point `run:` at whatever measures your pages.",
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 the tier you mean.",
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
- * @returns {Array<{id: string, level: string, mode: string, awaits: string|null, task: string|null, command: string|null, label: string, work: 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.
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 task =
2542
- entry.run ??
2543
- gate.run ??
2544
- definition?.taskAt?.[momentFamily(moment)] ??
2545
- definition?.task ??
2546
- null;
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
- .map(gate =>
2653
- gate.mode === "await" ? gate.awaits : `${workflowName} / ${gate.label}`
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 = auditConfigKeys(config).map(finding => finding.message);
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
- console.log(`${gate.level.padEnd(9)} ${gate.id.padEnd(28)} ${how}`);
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
- return ` ${token}${gate.level.padEnd(9)}${id}${detail}`;
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 four sources supplies this pair's task.
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":"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"}
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 four sources supplies this pair's task.
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":"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"}
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;