@codyswann/lisa 4.38.2 → 4.38.3

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 (65) hide show
  1. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  2. package/dist/core/lisa-owned-hash-ledger.js +2 -0
  3. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  4. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  5. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  6. package/dist/core/upstream-evidence-manifest.js +7 -3
  7. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  8. package/package.json +6 -5
  9. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +8 -0
  12. package/plugins/lisa-agy/plugin.json +1 -1
  13. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  16. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +8 -0
  20. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +8 -0
  22. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo-agy/plugin.json +1 -1
  25. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  35. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  40. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  45. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails-agy/plugin.json +1 -1
  50. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  55. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  60. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +8 -0
  63. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +8 -0
  64. package/scripts/check-typecheck-tests.mjs +147 -0
  65. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +8 -0
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Type-check `tests/` and hold the result to a quarantine that can only shrink.
4
+ *
5
+ * WHY THIS EXISTS. The required `type-correctness` gate compiles `tsconfig.json`,
6
+ * whose `include` is `src/**\/*`, so it compiled 0 of 1385 test files and reported
7
+ * success — a required gate permitting exactly what it forbids
8
+ * (CodySwannGT/lisa#3811). Test files here are not incidental: they hold fixture
9
+ * builders, shape assertions and harnesses other suites import.
10
+ *
11
+ * WHY A FILE-LEVEL QUARANTINE RATHER THAN A STAGED ROLLOUT. Turning the program
12
+ * on surfaces a backlog that predates this gate, so something has to hold it.
13
+ * The tempting option is to widen the program one directory at a time. That is
14
+ * the defect surviving in miniature: with a directory scope, a brand-new file
15
+ * under an unreached directory is unchecked on the day it is written. A
16
+ * file-level quarantine inverts it — **every new or renamed file is checked
17
+ * immediately**, and only the files that were already failing are exempt.
18
+ *
19
+ * IT RATCHETS IN BOTH DIRECTIONS, which is what stops it becoming permanent:
20
+ *
21
+ * - an error in a file NOT in the quarantine fails the gate: that is new debt;
22
+ * - a quarantined file with NO errors fails the gate too, asking to be
23
+ * removed from the list. Without that rule the list would record files that
24
+ * were fixed years ago and quietly re-authorise them if they regressed.
25
+ *
26
+ * `typecheck-quarantine.json` is additionally watched by the existing
27
+ * threshold-ratchet as an `allow-list` family, so *adding* an entry is flagged
28
+ * by a gate somebody already reads.
29
+ *
30
+ * WHAT IS DELIBERATELY NOT DONE HERE: the declared `lib` is not widened. tsc
31
+ * emits "Try changing the 'lib' compiler option to 'es2023' or later" on the
32
+ * ES2023 array APIs, and taking that suggestion would have erased the
33
+ * measurement proving this gap cost something — `toSorted` appeared 0 times in
34
+ * the type-checked `src/` and 52 times in the unchecked `tests/`. Those call
35
+ * sites were rewritten to ES2022 equivalents instead.
36
+ * @module scripts/check-typecheck-tests
37
+ */
38
+ import { spawnSync } from "node:child_process";
39
+ import { readFileSync } from "node:fs";
40
+ import * as path from "node:path";
41
+ import { fileURLToPath } from "node:url";
42
+
43
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
44
+ const QUARANTINE = path.join(ROOT, "typecheck-quarantine.json");
45
+ const PROJECT = path.join(ROOT, "tsconfig.tests.json");
46
+
47
+ /** Matches `path/to/file.ts(12,34): error TS1234: message`. */
48
+ const ERROR_LINE = /^(?<file>[^(]+)\((?<line>\d+),\d+\): error (?<code>TS\d+):/;
49
+
50
+ /**
51
+ * Read the quarantined paths.
52
+ * @returns {{files: string[], reason: string}} The parsed quarantine.
53
+ */
54
+ function readQuarantine() {
55
+ try {
56
+ const parsed = JSON.parse(readFileSync(QUARANTINE, "utf-8"));
57
+ return { files: parsed.files ?? [], reason: parsed.reason ?? "" };
58
+ } catch (error) {
59
+ console.error(
60
+ `check-typecheck-tests: cannot read ${path.relative(ROOT, QUARANTINE)} — ${error.message}`
61
+ );
62
+ console.error(
63
+ "That file is what makes this gate green, so an unreadable one is a refusal, not a pass."
64
+ );
65
+ process.exit(1);
66
+ }
67
+ }
68
+
69
+ const { files: quarantined } = readQuarantine();
70
+ const exempt = new Set(quarantined);
71
+
72
+ const tsc = spawnSync(
73
+ process.execPath,
74
+ [
75
+ path.join(ROOT, "node_modules", "typescript", "bin", "tsc"),
76
+ "--noEmit",
77
+ "-p",
78
+ PROJECT,
79
+ ],
80
+ { cwd: ROOT, encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }
81
+ );
82
+
83
+ if (tsc.error) {
84
+ console.error(
85
+ `check-typecheck-tests: could not run tsc — ${tsc.error.message}`
86
+ );
87
+ process.exit(1);
88
+ }
89
+
90
+ const lines = `${tsc.stdout ?? ""}\n${tsc.stderr ?? ""}`.split("\n");
91
+ /** @type {Map<string, number>} */
92
+ const errorsByFile = new Map();
93
+ for (const line of lines) {
94
+ const match = ERROR_LINE.exec(line.trim());
95
+ if (!match?.groups) continue;
96
+ const file = match.groups.file.replace(/\\/g, "/");
97
+ errorsByFile.set(file, (errorsByFile.get(file) ?? 0) + 1);
98
+ }
99
+
100
+ const offenders = [...errorsByFile.keys()]
101
+ .filter(file => !exempt.has(file))
102
+ .sort();
103
+ const cleared = quarantined.filter(file => !errorsByFile.has(file)).sort();
104
+
105
+ const totalErrors = [...errorsByFile.values()].reduce((sum, n) => sum + n, 0);
106
+ console.log(
107
+ `type-correctness (tests): ${errorsByFile.size} file(s) with ${totalErrors} error(s); ` +
108
+ `${quarantined.length} quarantined.`
109
+ );
110
+
111
+ if (offenders.length > 0) {
112
+ console.error("");
113
+ console.error(
114
+ `❌ ${offenders.length} file(s) outside the quarantine have type errors:`
115
+ );
116
+ for (const file of offenders) {
117
+ console.error(` ${file} (${errorsByFile.get(file)})`);
118
+ }
119
+ console.error("");
120
+ console.error(
121
+ "Fix them. Do NOT add them to typecheck-quarantine.json — that list"
122
+ );
123
+ console.error(
124
+ "only shrinks, and the threshold-ratchet flags additions to it."
125
+ );
126
+ }
127
+
128
+ if (cleared.length > 0) {
129
+ console.error("");
130
+ console.error(
131
+ `❌ ${cleared.length} quarantined file(s) now type-check and must leave the list:`
132
+ );
133
+ for (const file of cleared) console.error(` ${file}`);
134
+ console.error("");
135
+ console.error(
136
+ "Remove them from typecheck-quarantine.json. A list that keeps entries"
137
+ );
138
+ console.error(
139
+ "after they are fixed would re-authorise them if they ever regressed."
140
+ );
141
+ }
142
+
143
+ if (offenders.length > 0 || cleared.length > 0) process.exit(1);
144
+
145
+ console.log(
146
+ "✅ No type errors outside the quarantine, and no stale quarantine entries."
147
+ );
@@ -80,6 +80,14 @@ export const FAMILIES = [
80
80
  match: /(^|\/)\.lisa\.config\.json$/,
81
81
  kind: "allow-list",
82
82
  },
83
+ {
84
+ // The #3811 quarantine. `allow-list` is exactly right here: the list may
85
+ // shrink freely, and ADDING a file — re-authorising type debt that the
86
+ // gate would otherwise refuse — is the change that needs a human to see it.
87
+ id: "typecheck-quarantine",
88
+ match: /(^|\/)typecheck-quarantine\.json$/,
89
+ kind: "allow-list",
90
+ },
83
91
  {
84
92
  id: "lighthouse",
85
93
  match: /(^|\/)(?:lighthouserc-config|lighthouserc|\.lighthouserc)\.json$/,