@codyswann/lisa 3.40.4 → 3.41.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 (79) hide show
  1. package/all/copy-overwrite/scripts/lisa-gates.mjs +234 -1
  2. package/dist/cli/doctor-lisa-owned-artifacts.d.ts +4 -2
  3. package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -1
  4. package/dist/cli/doctor-lisa-owned-artifacts.js +46 -32
  5. package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -1
  6. package/dist/cli/doctor-lisa-owned-universal.d.ts +26 -0
  7. package/dist/cli/doctor-lisa-owned-universal.d.ts.map +1 -0
  8. package/dist/cli/doctor-lisa-owned-universal.js +50 -0
  9. package/dist/cli/doctor-lisa-owned-universal.js.map +1 -0
  10. package/dist/cli/doctor-skip-jobs-migration.d.ts +48 -0
  11. package/dist/cli/doctor-skip-jobs-migration.d.ts.map +1 -0
  12. package/dist/cli/doctor-skip-jobs-migration.js +271 -0
  13. package/dist/cli/doctor-skip-jobs-migration.js.map +1 -0
  14. package/dist/cli/doctor.d.ts.map +1 -1
  15. package/dist/cli/doctor.js +7 -0
  16. package/dist/cli/doctor.js.map +1 -1
  17. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  18. package/dist/core/lisa-owned-hash-ledger.js +1 -0
  19. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  20. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  21. package/dist/core/upstream-evidence-manifest.js +8 -2
  22. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  23. package/package.json +1 -1
  24. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa/.codex-plugin/skills/lisa-doctor/SKILL.md +20 -0
  27. package/plugins/lisa/skills/lisa-doctor/SKILL.md +20 -0
  28. package/plugins/lisa-agy/plugin.json +1 -1
  29. package/plugins/lisa-agy/skills/lisa-doctor/SKILL.md +20 -0
  30. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  33. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-copilot/skills/lisa-doctor/SKILL.md +20 -0
  37. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-cursor/skills/lisa-doctor/SKILL.md +20 -0
  39. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-expo-agy/plugin.json +1 -1
  42. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  47. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  52. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  57. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  62. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  66. package/plugins/lisa-rails-agy/plugin.json +1 -1
  67. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  72. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  76. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  77. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  79. package/plugins/src/base/skills/lisa-doctor/SKILL.md +20 -0
@@ -452,6 +452,213 @@ export const REGISTRY = Object.freeze({
452
452
  },
453
453
  });
454
454
 
455
+ /**
456
+ * Every `quality.yml` job that resolves through the gate façade, and its gate.
457
+ *
458
+ * This table and the two below exist so that the answer to "which gate replaces
459
+ * this `skip_jobs` token" can be read in a CONSUMER. It could not be, before:
460
+ * the pairs lived in one of Lisa's own test fixtures, which no consumer
461
+ * installs, so `lisa doctor` running in a caller repository and an agent working
462
+ * in a caller checkout both had nothing authoritative to consult.
463
+ *
464
+ * Eleven of the pairs cannot be recovered by transforming the name — `lint` is
465
+ * `code-style`, `sg_scan` is `structural-rules`, `work_item_traceability` is
466
+ * `traceability`. An underscore-to-hyphen guess gets a minority of them right,
467
+ * and being wrong here does not break a build: it declares the WRONG gate
468
+ * `off`, so a check silently stops running while the configuration reads
469
+ * deliberate. That is why this ships as data rather than as advice.
470
+ *
471
+ * It is STATIC on purpose. A consumer holds no copy of `quality.yml` — it calls
472
+ * the reusable workflow by ref — so the table cannot be derived where it is
473
+ * read. `tests/integration/quality-gate-skip-jobs-mapping.test.ts` derives it
474
+ * from the workflow in the one repository that has the workflow and fails when
475
+ * the two disagree, which is what keeps a static copy true.
476
+ */
477
+ export const QUALITY_JOB_GATES = Object.freeze({
478
+ lint: "code-style",
479
+ lint_slow: "code-style-slow",
480
+ typecheck: "type-correctness",
481
+ verification_coverage: "coverage-adequacy",
482
+ test_unit: "test-correctness",
483
+ test_mutation: "test-meaningfulness",
484
+ test_integration: "test-integration",
485
+ playwright_e2e_aggregate: "e2e-browser",
486
+ format: "format-conformance",
487
+ build: "build-integrity",
488
+ work_item_traceability: "traceability",
489
+ performance_budget: "performance-budget",
490
+ test_node_suites: "test-node-suites",
491
+ environment_reset: "environment-reset",
492
+ environment_reseed: "environment-reseed",
493
+ dead_code: "dead-code",
494
+ sg_scan: "structural-rules",
495
+ npm_security_scan: "dependency-vulnerability",
496
+ });
497
+
498
+ /**
499
+ * Every `skip_jobs` token `quality.yml` honours or advertises, and the jobs it
500
+ * suppresses.
501
+ *
502
+ * Keyed by TOKEN, not by job id, because the two differ and the difference is
503
+ * invisible from either side: the token is `test:unit` and the job is
504
+ * `test_unit`, so a table keyed on job ids answers "no such token" for three of
505
+ * the tokens that do have gates.
506
+ *
507
+ * An empty array is a real entry, not a placeholder. `github_issue` is
508
+ * advertised by the input's own description and honoured by no job at all — it
509
+ * suppresses nothing today, which a consumer deleting it deserves to be told
510
+ * rather than left to infer from a check that never changed.
511
+ */
512
+ export const SKIP_JOB_TOKENS = Object.freeze({
513
+ lint: Object.freeze(["lint"]),
514
+ lint_slow: Object.freeze(["lint_slow"]),
515
+ typecheck: Object.freeze(["typecheck"]),
516
+ e2e_coverage: Object.freeze(["e2e_coverage"]),
517
+ state_classification: Object.freeze(["state_classification"]),
518
+ bdd_coverage: Object.freeze(["bdd_coverage"]),
519
+ learnings_budget: Object.freeze(["learnings_budget"]),
520
+ "test:unit": Object.freeze(["test_unit"]),
521
+ "test:mutation": Object.freeze(["test_mutation"]),
522
+ "test:integration": Object.freeze(["test_integration"]),
523
+ "test:e2e": Object.freeze(["test_e2e"]),
524
+ maestro_e2e: Object.freeze(["maestro_e2e"]),
525
+ // Three jobs, one token, and only the last of them has a façade. Reporting
526
+ // this as a clean swap would be the most expensive wrong answer in the table:
527
+ // the shards keep running, so an operator who deleted the token would see the
528
+ // work continue and conclude the declaration had not taken effect.
529
+ playwright_e2e: Object.freeze([
530
+ "playwright_e2e_setup",
531
+ "playwright_e2e",
532
+ "playwright_e2e_aggregate",
533
+ ]),
534
+ format: Object.freeze(["format"]),
535
+ build: Object.freeze(["build"]),
536
+ skipped_required_checks: Object.freeze(["skipped_required_checks"]),
537
+ threshold_ratchet: Object.freeze(["threshold_ratchet"]),
538
+ work_item_traceability: Object.freeze(["work_item_traceability"]),
539
+ test_node_suites: Object.freeze(["test_node_suites"]),
540
+ environment_reset: Object.freeze(["environment_reset"]),
541
+ environment_reseed: Object.freeze(["environment_reseed"]),
542
+ dead_code: Object.freeze(["dead_code"]),
543
+ sg_scan: Object.freeze(["sg_scan"]),
544
+ floor_collisions: Object.freeze(["floor_collisions"]),
545
+ npm_security_scan: Object.freeze(["npm_security_scan"]),
546
+ sonarcloud: Object.freeze(["sonarcloud"]),
547
+ snyk: Object.freeze(["snyk"]),
548
+ secret_scanning: Object.freeze(["secret_scanning"]),
549
+ license_compliance: Object.freeze(["license_compliance"]),
550
+ zap_baseline: Object.freeze(["zap_baseline"]),
551
+ github_issue: Object.freeze([]),
552
+ });
553
+
554
+ /**
555
+ * What a `skip_jobs` token can be resolved to.
556
+ *
557
+ * Four of the five are refusals, which is the point. The failure this table
558
+ * exists to prevent is a confident wrong answer, so anything short of "one gate
559
+ * covers every job this token suppresses" has to be a distinct, nameable
560
+ * outcome rather than a best effort.
561
+ */
562
+ export const SKIP_JOB_STATUS = [
563
+ "replaceable",
564
+ "partial",
565
+ "unmappable",
566
+ "inert",
567
+ "unknown",
568
+ "moment-illegal",
569
+ ];
570
+
571
+ /**
572
+ * Resolve one `skip_jobs` token to the gate declaration that replaces it.
573
+ * @param {string} token A `skip_jobs` token, exactly as the caller spells it.
574
+ * @returns {{token: string, status: string, jobs: string[], gates: string[], gate: string|null, ungated: string[]}} What is known about the token.
575
+ */
576
+ export function gateForSkipJob(token) {
577
+ const jobs = Object.hasOwn(SKIP_JOB_TOKENS, token)
578
+ ? [...SKIP_JOB_TOKENS[token]]
579
+ : null;
580
+ if (jobs === null) {
581
+ // Not a guess declined — a token this workflow has never had. A caller can
582
+ // reach here by typo, by whitespace (`'lint, lint_slow'` yields the token
583
+ // `" lint_slow"`), or by carrying a token from a workflow that predates
584
+ // this one. All three suppress nothing today, and none of them may be
585
+ // answered with the nearest-looking gate.
586
+ return {
587
+ token,
588
+ status: "unknown",
589
+ jobs: [],
590
+ gates: [],
591
+ gate: null,
592
+ ungated: [],
593
+ };
594
+ }
595
+
596
+ const ungated = jobs.filter(job => !Object.hasOwn(QUALITY_JOB_GATES, job));
597
+ const gates = [
598
+ ...new Set(
599
+ jobs.flatMap(job =>
600
+ Object.hasOwn(QUALITY_JOB_GATES, job) ? [QUALITY_JOB_GATES[job]] : []
601
+ )
602
+ ),
603
+ ];
604
+
605
+ const status =
606
+ jobs.length === 0
607
+ ? "inert"
608
+ : gates.length === 0
609
+ ? "unmappable"
610
+ : gates.length === 1 && ungated.length === 0
611
+ ? "replaceable"
612
+ : "partial";
613
+
614
+ return {
615
+ token,
616
+ status,
617
+ jobs,
618
+ gates,
619
+ // One gate or none. Two gates behind one token means no single declaration
620
+ // replaces it, and picking either would turn off half of what the token
621
+ // turns off while reading as a complete migration.
622
+ gate: gates.length === 1 ? gates[0] : null,
623
+ ungated,
624
+ };
625
+ }
626
+
627
+ /**
628
+ * Resolve a token to the declaration that replaces it AT ONE MOMENT.
629
+ *
630
+ * The moment is not decoration. `quality.yml` takes it as an input, every job
631
+ * resolves its gate at it, and a gate's registry entry names the closed set of
632
+ * moments it may legally be declared at — `traceability` at `push` and
633
+ * `pull-request` and nowhere else. So a caller running the pre-deploy set has
634
+ * no legal declaration for that token, and printing one anyway would be
635
+ * refused by `validate` AFTER the operator had already deleted the token,
636
+ * leaving the check running unguarded with the configuration reading migrated.
637
+ *
638
+ * Emitted by both `lisa doctor` and this file's `skip-jobs` command, from here,
639
+ * so the string an operator is shown cannot differ between the two.
640
+ * @param {string} token A `skip_jobs` token, exactly as the caller spells it.
641
+ * @param {string} [moment] The moment the caller passes to `quality.yml`.
642
+ * @returns {{token: string, status: string, moment: string, jobs: string[], gates: string[], gate: string|null, ungated: string[], declaration: string|null}} The migration for that token.
643
+ */
644
+ export function skipJobMigration(token, moment = "pull-request") {
645
+ const resolved = gateForSkipJob(token);
646
+ if (resolved.gate === null) {
647
+ return { ...resolved, moment, declaration: null };
648
+ }
649
+ const permitted =
650
+ isMoment(moment) &&
651
+ (REGISTRY[resolved.gate]?.moments ?? []).includes(momentFamily(moment));
652
+ if (!permitted) {
653
+ return { ...resolved, moment, status: "moment-illegal", declaration: null };
654
+ }
655
+ return {
656
+ ...resolved,
657
+ moment,
658
+ declaration: `"${resolved.gate}": { "${moment}": "off" }`,
659
+ };
660
+ }
661
+
455
662
  /**
456
663
  * Guarantees the platform enforces, which no task can implement.
457
664
  *
@@ -1414,6 +1621,32 @@ function main() {
1414
1621
  return;
1415
1622
  }
1416
1623
 
1624
+ if (command === "skip-jobs") {
1625
+ // Deliberately not gated on reading .lisa.config.json: this answers "what
1626
+ // would replace this token", which a repository that has not migrated yet
1627
+ // must be able to ask. It is the surface an agent in a consumer checkout
1628
+ // uses, so it must work before anything has been declared.
1629
+ const requested = (flag("tokens") ?? "")
1630
+ .split(",")
1631
+ .filter(entry => entry !== "");
1632
+ const moment = flag("moment") ?? "pull-request";
1633
+ const resolved = (
1634
+ requested.length ? requested : Object.keys(SKIP_JOB_TOKENS)
1635
+ ).map(token => skipJobMigration(token, moment));
1636
+ if (rest.includes("--json")) {
1637
+ console.log(JSON.stringify(resolved, null, 2));
1638
+ return;
1639
+ }
1640
+ for (const entry of resolved) {
1641
+ console.log(
1642
+ `${entry.token.padEnd(24)} ${entry.status.padEnd(15)} ${
1643
+ entry.declaration ?? "(no declaration — see status)"
1644
+ }`
1645
+ );
1646
+ }
1647
+ return;
1648
+ }
1649
+
1417
1650
  if (command === "audit-config") {
1418
1651
  const findings = auditConfigKeys(config);
1419
1652
  for (const finding of findings) console.error(` ${finding.message}`);
@@ -1422,7 +1655,7 @@ function main() {
1422
1655
  }
1423
1656
 
1424
1657
  throw new Error(
1425
- "usage: lisa-gates.mjs validate|list|needs|contexts|audit-config"
1658
+ "usage: lisa-gates.mjs validate|list|needs|contexts|skip-jobs|audit-config"
1426
1659
  );
1427
1660
  }
1428
1661
 
@@ -15,8 +15,10 @@ interface ArtifactCheck {
15
15
  * nobody can account for is worth a line either way, and staying silent about a
16
16
  * downstream edit would let a project quietly swap a guard for a stub.
17
17
  *
18
- * Only artifacts the project already has are considered: a missing one means
19
- * the stack does not apply here, not that something drifted.
18
+ * A third finding covers absence, but only for the universal tree. A missing
19
+ * stack-specific artifact means that stack does not apply here, which is not
20
+ * drift. A missing universal one means apply has not run, and the CI gate that
21
+ * calls it is not running at all.
20
22
  * @param targetPath - Project path to inspect
21
23
  * @param lisaRoot - Installed Lisa package root (injected by tests)
22
24
  * @param ledger - Known-good hashes, defaulting to Lisa's shipping history
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-lisa-owned-artifacts.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAwBnE,wEAAwE;AACxE,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAwHD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAA0B,EACpC,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,aAAa,CAAC,CA8CxB"}
1
+ {"version":3,"file":"doctor-lisa-owned-artifacts.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AA0BnE,wEAAwE;AACxE,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AA8FD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAA0B,EACpC,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,aAAa,CAAC,CAgDxB"}
@@ -18,16 +18,13 @@
18
18
  import { readFile } from "node:fs/promises";
19
19
  import * as path from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
- import * as fse from "fs-extra";
22
21
  import { PROJECT_TYPE_ORDER } from "../core/config.js";
23
22
  import { classifyHostCopy, mayRefreshLisaOwned, } from "../core/lisa-owned-provenance.js";
24
- import { isLisaOwnedTemplate } from "../core/lisa-owned-templates.js";
25
23
  import { isLisaSourceRepo } from "../core/self-apply.js";
26
- import { listFilesRecursive } from "../utils/file-operations.js";
27
24
  import { matchesAnyPattern, parseIgnorePatterns, } from "../utils/ignore-patterns.js";
28
25
  import { describeResolvableCopies, } from "./doctor-lisa-owned-artifact-copies.js";
26
+ import { shippedByStack, UNIVERSAL_STACK, universalDestinations, } from "./doctor-lisa-owned-universal.js";
29
27
  const CHECK_NAME = "Lisa enforcement artifacts current?";
30
- const COPY_OVERWRITE = "copy-overwrite";
31
28
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
32
29
  /**
33
30
  * Quoted relative module specifiers — `import`/`export from`, `require()`, and
@@ -42,23 +39,6 @@ const RELATIVE_SPECIFIER = /["'`](\.\.?\/[^"'`\n]{1,4096})["'`]/g;
42
39
  function defaultLisaRoot() {
43
40
  return path.resolve(__dirname, "..", "..");
44
41
  }
45
- /**
46
- * List the Lisa-owned artifacts one stack's copy-overwrite tree ships.
47
- * @param lisaRoot - Installed Lisa package root
48
- * @param type - Stack directory name
49
- * @returns Destination/source pairs shipped by that stack
50
- */
51
- async function shippedByStack(lisaRoot, type) {
52
- const directory = path.join(lisaRoot, type, COPY_OVERWRITE);
53
- if (!(await fse.pathExists(directory)))
54
- return [];
55
- return (await listFilesRecursive(directory))
56
- .map(source => [
57
- path.relative(directory, source).split(path.sep).join("/"),
58
- source,
59
- ])
60
- .filter(([destination]) => isLisaOwnedTemplate(destination));
61
- }
62
42
  /**
63
43
  * Collect every shipped Lisa-owned artifact, keyed by its destination path.
64
44
  *
@@ -69,7 +49,7 @@ async function shippedByStack(lisaRoot, type) {
69
49
  * @returns Destination path to the shipped source files that produce it
70
50
  */
71
51
  async function shippedArtifacts(lisaRoot) {
72
- const shipped = (await Promise.all(["all", ...PROJECT_TYPE_ORDER].map(async (type) => shippedByStack(lisaRoot, type)))).flat();
52
+ const shipped = (await Promise.all([UNIVERSAL_STACK, ...PROJECT_TYPE_ORDER].map(async (type) => shippedByStack(lisaRoot, type)))).flat();
73
53
  const destinations = [
74
54
  ...new Set(shipped.map(([destination]) => destination)),
75
55
  ];
@@ -123,8 +103,10 @@ function reExportsShippedTemplate(installed, installedPath, sources) {
123
103
  * nobody can account for is worth a line either way, and staying silent about a
124
104
  * downstream edit would let a project quietly swap a guard for a stub.
125
105
  *
126
- * Only artifacts the project already has are considered: a missing one means
127
- * the stack does not apply here, not that something drifted.
106
+ * A third finding covers absence, but only for the universal tree. A missing
107
+ * stack-specific artifact means that stack does not apply here, which is not
108
+ * drift. A missing universal one means apply has not run, and the CI gate that
109
+ * calls it is not running at all.
128
110
  * @param targetPath - Project path to inspect
129
111
  * @param lisaRoot - Installed Lisa package root (injected by tests)
130
112
  * @param ledger - Known-good hashes, defaulting to Lisa's shipping history
@@ -132,6 +114,7 @@ function reExportsShippedTemplate(installed, installedPath, sources) {
132
114
  */
133
115
  export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisaRoot(), ledger) {
134
116
  const shipped = await shippedArtifacts(lisaRoot);
117
+ const universal = await universalDestinations(lisaRoot);
135
118
  if (shipped.size === 0) {
136
119
  return {
137
120
  name: CHECK_NAME,
@@ -146,7 +129,7 @@ export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisa
146
129
  // unless the target's package.json is Lisa itself. A host must not be able to
147
130
  // swap a guard for a thin re-export and have doctor call it current.
148
131
  const selfHost = await isLisaSourceRepo(targetPath);
149
- const results = await Promise.all([...shipped].map(async ([destination, sources]) => assessArtifact(targetPath, lisaRoot, destination, sources, ignorePatterns, selfHost, ledger)));
132
+ const results = await Promise.all([...shipped].map(async ([destination, sources]) => assessArtifact(targetPath, lisaRoot, destination, sources, ignorePatterns, selfHost, universal.has(destination), ledger)));
150
133
  const assessments = results.filter((item) => item !== undefined);
151
134
  return summarise(assessments
152
135
  .map(item => item.finding)
@@ -162,19 +145,16 @@ export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisa
162
145
  * @param sources - Absolute shipped package variants
163
146
  * @param ignorePatterns - Parsed .lisaignore patterns
164
147
  * @param selfHost - Whether the target is Lisa's own source repository
148
+ * @param universal - Whether every project receives this destination
165
149
  * @param ledger - Known-good hashes, defaulting to Lisa's shipping history
166
- * @returns Per-artifact assessment, or undefined when no installed copy exists
150
+ * @returns Per-artifact assessment, or undefined when nothing is reportable
167
151
  */
168
- async function assessArtifact(targetPath, lisaRoot, destination, sources, ignorePatterns, selfHost, ledger) {
152
+ async function assessArtifact(targetPath, lisaRoot, destination, sources, ignorePatterns, selfHost, universal, ledger) {
169
153
  const installedPath = path.join(targetPath, destination);
170
154
  const installed = await readFile(installedPath).catch(() => undefined);
171
155
  const ignored = matchesAnyPattern(destination, ignorePatterns);
172
156
  if (installed === undefined) {
173
- return ignored
174
- ? {
175
- finding: [destination, "ignored"],
176
- }
177
- : undefined;
157
+ return assessAbsent(destination, ignored, universal, selfHost);
178
158
  }
179
159
  const multiCopy = await describeResolvableCopies(lisaRoot, destination, installed, sources);
180
160
  if (ignored)
@@ -188,6 +168,35 @@ async function assessArtifact(targetPath, lisaRoot, destination, sources, ignore
188
168
  const outdated = await isProvablyStale(installed, destination, sources, ledger);
189
169
  return withMultiCopy([destination, outdated ? "stale" : "modified"], multiCopy);
190
170
  }
171
+ /**
172
+ * Assess a Lisa-owned artifact the project does not have.
173
+ *
174
+ * An absent stack-specific artifact means that stack does not apply here, which
175
+ * is not drift — that exemption is why absence used to report nothing at all.
176
+ * It over-reached: a universal artifact has no stack it does not apply to, so
177
+ * its absence means apply never ran and the CI gate that calls it is not
178
+ * running. Measured on `scripts/lisa-floor-collisions.mjs` (#2731), whose job
179
+ * exited 0 on the missing script — green, having examined nothing, with doctor
180
+ * silent too. Fixing only the job turns a silent pass into a red nobody has
181
+ * been told how to clear.
182
+ *
183
+ * Never for Lisa's own repository: it is the source of these artifacts, not a
184
+ * consumer, and installs only the few it runs on itself, so "apply never ran"
185
+ * is a category error there.
186
+ * @param destination - Project-relative artifact destination
187
+ * @param ignored - Whether .lisaignore names this destination
188
+ * @param universal - Whether every project receives this destination
189
+ * @param selfHost - Whether the target is Lisa's own source repository
190
+ * @returns Per-artifact assessment, or undefined when absence proves nothing
191
+ */
192
+ function assessAbsent(destination, ignored, universal, selfHost) {
193
+ if (ignored) {
194
+ return { finding: [destination, "ignored"] };
195
+ }
196
+ return universal && !selfHost
197
+ ? { finding: [destination, "missing"] }
198
+ : undefined;
199
+ }
191
200
  /**
192
201
  * Attach optional multi-copy provenance without materialising undefined fields.
193
202
  * @param finding - Artifact finding tuple
@@ -211,10 +220,12 @@ function summarise(findings, multiCopies) {
211
220
  const stale = pick("stale");
212
221
  const modified = pick("modified");
213
222
  const ignored = pick("ignored");
223
+ const missing = pick("missing");
214
224
  const copyDisagreements = multiCopies.filter(copy => copy.disagrees);
215
225
  const copyReports = renderCopyReports(multiCopies);
216
226
  const warningFree = stale.length === 0 &&
217
227
  modified.length === 0 &&
228
+ missing.length === 0 &&
218
229
  copyDisagreements.length === 0;
219
230
  if (warningFree) {
220
231
  // Named rather than folded into the pass. A guard excluded by
@@ -231,6 +242,9 @@ function summarise(findings, multiCopies) {
231
242
  ignored.length > 0
232
243
  ? `${ignored.length} not assessed (.lisaignore): ${ignored.join(", ")}`
233
244
  : "",
245
+ missing.length > 0
246
+ ? `Lisa-owned guards every project receives are not installed, so the CI gates that call them run against nothing (run \`npx lisa apply .\` to install them): ${missing.join(", ")}`
247
+ : "",
234
248
  stale.length > 0
235
249
  ? `Outdated Lisa-owned guards (run \`npx lisa apply .\` to refresh): ${stale.join(", ")}`
236
250
  : "",
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-lisa-owned-artifacts.js","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor-lisa-owned-artifacts.js","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /** Directory name of the strategy tree these artifacts are shipped from. */
2
+ export declare const COPY_OVERWRITE = "copy-overwrite";
3
+ /**
4
+ * The stack tree every project receives regardless of detected type.
5
+ *
6
+ * `Lisa.processProjectType("all")` runs unconditionally and every downstream
7
+ * loop is `["all", ...detectedTypes]`, so an artifact shipped here has no stack
8
+ * it legitimately does not apply to.
9
+ */
10
+ export declare const UNIVERSAL_STACK = "all";
11
+ /** One shipped Lisa-owned artifact and the destination it installs to. */
12
+ export type ShippedArtifact = readonly [destination: string, source: string];
13
+ /**
14
+ * List the Lisa-owned artifacts one stack's copy-overwrite tree ships.
15
+ * @param lisaRoot - Installed Lisa package root
16
+ * @param type - Stack directory name
17
+ * @returns Destination/source pairs shipped by that stack
18
+ */
19
+ export declare function shippedByStack(lisaRoot: string, type: string): Promise<readonly ShippedArtifact[]>;
20
+ /**
21
+ * Destinations shipped by the universal tree, which every project receives.
22
+ * @param lisaRoot - Installed Lisa package root
23
+ * @returns Destination paths no project can legitimately be without
24
+ */
25
+ export declare function universalDestinations(lisaRoot: string): Promise<ReadonlySet<string>>;
26
+ //# sourceMappingURL=doctor-lisa-owned-universal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-lisa-owned-universal.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-universal.ts"],"names":[],"mappings":"AAgBA,4EAA4E;AAC5E,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7E;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAYrC;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAM9B"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Which Lisa-owned artifacts every project receives, whatever stack it is.
3
+ *
4
+ * Kept separate from `doctor-lisa-owned-artifacts.ts` for the max-lines budget,
5
+ * the same way the safety-net fixtures are split. The distinction it encodes is
6
+ * small but load-bearing: absence of a STACK artifact proves nothing, because
7
+ * that stack may simply not apply here, while absence of a UNIVERSAL one means
8
+ * apply never ran and the CI gate that calls it is not running at all.
9
+ * @module cli/doctor-lisa-owned-universal
10
+ */
11
+ import * as path from "node:path";
12
+ import * as fse from "fs-extra";
13
+ import { isLisaOwnedTemplate } from "../core/lisa-owned-templates.js";
14
+ import { listFilesRecursive } from "../utils/file-operations.js";
15
+ /** Directory name of the strategy tree these artifacts are shipped from. */
16
+ export const COPY_OVERWRITE = "copy-overwrite";
17
+ /**
18
+ * The stack tree every project receives regardless of detected type.
19
+ *
20
+ * `Lisa.processProjectType("all")` runs unconditionally and every downstream
21
+ * loop is `["all", ...detectedTypes]`, so an artifact shipped here has no stack
22
+ * it legitimately does not apply to.
23
+ */
24
+ export const UNIVERSAL_STACK = "all";
25
+ /**
26
+ * List the Lisa-owned artifacts one stack's copy-overwrite tree ships.
27
+ * @param lisaRoot - Installed Lisa package root
28
+ * @param type - Stack directory name
29
+ * @returns Destination/source pairs shipped by that stack
30
+ */
31
+ export async function shippedByStack(lisaRoot, type) {
32
+ const directory = path.join(lisaRoot, type, COPY_OVERWRITE);
33
+ if (!(await fse.pathExists(directory)))
34
+ return [];
35
+ return (await listFilesRecursive(directory))
36
+ .map(source => [
37
+ path.relative(directory, source).split(path.sep).join("/"),
38
+ source,
39
+ ])
40
+ .filter(([destination]) => isLisaOwnedTemplate(destination));
41
+ }
42
+ /**
43
+ * Destinations shipped by the universal tree, which every project receives.
44
+ * @param lisaRoot - Installed Lisa package root
45
+ * @returns Destination paths no project can legitimately be without
46
+ */
47
+ export async function universalDestinations(lisaRoot) {
48
+ return new Set((await shippedByStack(lisaRoot, UNIVERSAL_STACK)).map(([destination]) => destination));
49
+ }
50
+ //# sourceMappingURL=doctor-lisa-owned-universal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-lisa-owned-universal.js","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-universal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEjE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAKrC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAgB,EAChB,IAAY;IAEZ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClD,OAAO,CAAC,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC;SACzC,GAAG,CACF,MAAM,CAAC,EAAE,CACP;QACE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC1D,MAAM;KACE,CACb;SACA,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB;IAEhB,OAAO,IAAI,GAAG,CACZ,CAAC,MAAM,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,CACnD,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,WAAW,CAC/B,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { DoctorCheck } from "./doctor.js";
2
+ /** One token's migration, exactly as the shipped registry resolves it. */
3
+ export interface SkipJobToken {
4
+ /** The token as the caller spells it, including any damaging whitespace. */
5
+ readonly token: string;
6
+ /** One of the registry's `SKIP_JOB_STATUS` values. */
7
+ readonly status: string;
8
+ /** The gate that replaces it, or null when there is none. */
9
+ readonly gate: string | null;
10
+ /** The `quality.yml` jobs the token suppresses. */
11
+ readonly jobs: readonly string[];
12
+ /** Suppressed jobs with no gate — these keep running after the migration. */
13
+ readonly ungated: readonly string[];
14
+ /** The `.lisa.config.json` fragment to write, or null when none exists. */
15
+ readonly declaration: string | null;
16
+ }
17
+ /** One caller workflow that still passes `skip_jobs`. */
18
+ export interface SkipJobCaller {
19
+ /** Workflow file, relative to the project root. */
20
+ readonly file: string;
21
+ /** The moment that caller resolves gates at. */
22
+ readonly moment: string;
23
+ /** Every token it passes, in the order it passes them. */
24
+ readonly tokens: readonly SkipJobToken[];
25
+ }
26
+ /**
27
+ * Every caller in a project that still passes `skip_jobs`, with its migration.
28
+ * @param targetPath - Project root
29
+ * @returns One entry per `skip_jobs` input carrying at least one token
30
+ */
31
+ export declare function skipJobCallers(targetPath: string): Promise<SkipJobCaller[]>;
32
+ /**
33
+ * The operator-readable line for one token.
34
+ * @param entry - The token's resolved migration
35
+ * @returns One line naming the edit, or naming why there is none
36
+ */
37
+ export declare function describeToken(entry: SkipJobToken): string;
38
+ /**
39
+ * Report the gate declarations that replace a caller's `skip_jobs` tokens.
40
+ *
41
+ * Reports only. `ci.yml` ships create-only, so `lisa apply` never refreshes it
42
+ * and the migration is a consumer-side edit either way — but the reason this
43
+ * does not write is the one in the module docstring, not that one.
44
+ * @param targetPath - Project path to inspect
45
+ * @returns Doctor check result
46
+ */
47
+ export declare function checkSkipJobsMigration(targetPath: string): Promise<DoctorCheck>;
48
+ //# sourceMappingURL=doctor-skip-jobs-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-skip-jobs-migration.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-skip-jobs-migration.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAgB/C,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;CAC1C;AA6KD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,EAAE,CAAC,CAQ1B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CA4BzD;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CAoCtB"}