@codyswann/lisa 4.42.7 → 4.43.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 (91) hide show
  1. package/dist/cli/doctor-readiness-delivery.d.ts.map +1 -1
  2. package/dist/cli/doctor-readiness-delivery.js +13 -6
  3. package/dist/cli/doctor-readiness-delivery.js.map +1 -1
  4. package/dist/cli/doctor-readiness-deploy-outcome.d.ts +9 -0
  5. package/dist/cli/doctor-readiness-deploy-outcome.d.ts.map +1 -0
  6. package/dist/cli/doctor-readiness-deploy-outcome.js +87 -0
  7. package/dist/cli/doctor-readiness-deploy-outcome.js.map +1 -0
  8. package/dist/cli/doctor-readiness-workflows.d.ts +8 -0
  9. package/dist/cli/doctor-readiness-workflows.d.ts.map +1 -1
  10. package/dist/cli/doctor-readiness-workflows.js +1 -0
  11. package/dist/cli/doctor-readiness-workflows.js.map +1 -1
  12. package/dist/core/deploy-release-dependence.d.ts +72 -0
  13. package/dist/core/deploy-release-dependence.d.ts.map +1 -0
  14. package/dist/core/deploy-release-dependence.js +236 -0
  15. package/dist/core/deploy-release-dependence.js.map +1 -0
  16. package/dist/core/github-actions-condition.d.ts +78 -0
  17. package/dist/core/github-actions-condition.d.ts.map +1 -0
  18. package/dist/core/github-actions-condition.js +307 -0
  19. package/dist/core/github-actions-condition.js.map +1 -0
  20. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  21. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  22. package/dist/core/upstream-evidence-manifest.js +15 -1
  23. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  24. package/dist/migrations/deploy-outcome-guard-edit.d.ts +11 -0
  25. package/dist/migrations/deploy-outcome-guard-edit.d.ts.map +1 -0
  26. package/dist/migrations/deploy-outcome-guard-edit.js +184 -0
  27. package/dist/migrations/deploy-outcome-guard-edit.js.map +1 -0
  28. package/dist/migrations/deploy-outcome-guard-yaml.d.ts +91 -0
  29. package/dist/migrations/deploy-outcome-guard-yaml.d.ts.map +1 -0
  30. package/dist/migrations/deploy-outcome-guard-yaml.js +180 -0
  31. package/dist/migrations/deploy-outcome-guard-yaml.js.map +1 -0
  32. package/dist/migrations/ensure-deploy-outcome-guard.d.ts +41 -0
  33. package/dist/migrations/ensure-deploy-outcome-guard.d.ts.map +1 -0
  34. package/dist/migrations/ensure-deploy-outcome-guard.js +238 -0
  35. package/dist/migrations/ensure-deploy-outcome-guard.js.map +1 -0
  36. package/dist/migrations/index.d.ts +1 -0
  37. package/dist/migrations/index.d.ts.map +1 -1
  38. package/dist/migrations/index.js +3 -0
  39. package/dist/migrations/index.js.map +1 -1
  40. package/package.json +4 -4
  41. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-agy/plugin.json +1 -1
  44. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  47. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-expo-agy/plugin.json +1 -1
  54. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  59. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  64. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  69. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  74. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-rails-agy/plugin.json +1 -1
  79. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  84. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  88. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  89. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  91. package/scripts/check-test-case-executed.mjs +184 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.42.7",
3
+ "version": "4.43.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Proves that a NAMED test case actually EXECUTED, from a vitest JSON report.
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * An assertion about a configuration is not an assertion about execution, and
8
+ * CodySwannGT/lisa#3935 is what that gap costs. A 100,000-entry temp-scan
9
+ * benchmark was moved off the pre-push gate on the stated grounds that CI still
10
+ * ran it. It did not: the case is `it.runIf(process.platform === "darwin")` and
11
+ * every CI runner is `ubuntu-latest`, so CI skipped it, and had always skipped
12
+ * it. The check written to guard the move asserted that the pull-request task
13
+ * did not EXCLUDE the file — true, and hollow, because a platform guard one
14
+ * layer down skipped the case anyway. Not excluding a file is not running it.
15
+ *
16
+ * A skipped case is a green case. Nothing in the pipeline reports it, because
17
+ * from the runner's point of view nothing went wrong. That is the whole failure
18
+ * mode: the surface reads as covered while running nothing.
19
+ *
20
+ * So this script asserts the only thing that settles the question — that the
21
+ * case appears in the report, that it PASSED rather than being skipped or
22
+ * todo-ed, and that it consumed real wall-clock time. A lane that runs it is
23
+ * then a lane that can PROVE it ran it, and a platform guard that silently
24
+ * removes the case turns a green job red with the reason on screen.
25
+ *
26
+ * ## Vitest's report vocabulary, as observed
27
+ *
28
+ * Measured on vitest 4.1.9 against a deliberate `it.runIf(false)` probe: a
29
+ * guarded-off case is present in `testResults[].assertionResults[]` with
30
+ * `status: "skipped"` and NO `duration` field, and is counted in
31
+ * `numPendingTests`. A case whose whole FILE was never collected — an
32
+ * `--exclude` glob, a moved file, a typo in the path — is absent from the
33
+ * report entirely. Both are execution failures and both are reported here,
34
+ * separately, because they have different fixes: one is a platform or flag
35
+ * guard, the other is a path or exclusion.
36
+ *
37
+ * `fullName` joins `ancestorTitles` to the title with a SPACE. `vitest list`
38
+ * prints the same case with ` > ` between them, and the two are easy to
39
+ * confuse — measured, both forms, on the same suite. A caller that passes the
40
+ * wrong form gets a case that is absent for a reason having nothing to do with
41
+ * execution, so an ABSENT failure PRINTS the names the report did contain
42
+ * rather than asserting the case was never collected. A gate whose diagnosis is
43
+ * confidently wrong costs more than one that says less.
44
+ *
45
+ * ## Usage
46
+ *
47
+ * node scripts/check-test-case-executed.mjs \
48
+ * --report <vitest --reporter=json --outputFile target> \
49
+ * --name "<full test name>" [--name "<another>"]
50
+ *
51
+ * Exit 0 only when EVERY named case is present, passed, and timed. Any other
52
+ * outcome exits 1 and names which case and which way it failed.
53
+ * @module scripts/check-test-case-executed
54
+ */
55
+ import { readFileSync } from "node:fs";
56
+
57
+ import { invokedAsScript } from "./lib/invoked-as-script.mjs";
58
+
59
+ /**
60
+ * Statuses vitest reports for a case that did not actually run.
61
+ *
62
+ * A Map rather than an object literal because the key is a status string read
63
+ * out of a JSON file. On an object, a report carrying `"constructor"` or
64
+ * `"toString"` resolves to something inherited from `Object.prototype` and the
65
+ * message below stringifies it as though it were advice — an absurd input, but
66
+ * this gate's whole job is to be right about a file it did not write.
67
+ */
68
+ const NON_EXECUTED_STATUS_ADVICE = new Map([
69
+ [
70
+ "skipped",
71
+ "the case was SKIPPED — a platform guard, a `runIf` condition, or an `it.skip` removed it; a skipped case is a green case and proves nothing",
72
+ ],
73
+ ["todo", "the case is marked TODO — it has no body to execute"],
74
+ [
75
+ "failed",
76
+ "the case RAN and FAILED — read the failure above; this gate only reports that it was not a passing execution",
77
+ ],
78
+ ]);
79
+
80
+ /**
81
+ * Parse `--report <path>` and one or more `--name <full test name>` flags.
82
+ * @param {readonly string[]} argv - Arguments after the script path
83
+ * @returns {{report: string, names: readonly string[]}} Validated invocation
84
+ */
85
+ export function parseArguments(argv) {
86
+ const names = [];
87
+ let report;
88
+ for (let index = 0; index < argv.length; index += 1) {
89
+ const flag = argv[index];
90
+ const value = argv[index + 1];
91
+ if (flag !== "--report" && flag !== "--name")
92
+ throw new Error(`Unknown argument: ${String(flag)}`);
93
+ if (value === undefined || value.startsWith("--"))
94
+ throw new Error(`${flag} requires a value`);
95
+ if (flag === "--report") report = value;
96
+ else names.push(value);
97
+ index += 1;
98
+ }
99
+ if (report === undefined) throw new Error("--report is required");
100
+ if (names.length === 0) throw new Error("At least one --name is required");
101
+ return { report, names };
102
+ }
103
+
104
+ /**
105
+ * Read every case the report contains, keyed by its full name.
106
+ * @param {string} reportPath - Path to a vitest JSON report
107
+ * @returns {Map<string, {status: string, duration?: number}>} Reported cases
108
+ */
109
+ export function reportedCases(reportPath) {
110
+ let parsed;
111
+ try {
112
+ parsed = JSON.parse(readFileSync(reportPath, "utf8"));
113
+ } catch (cause) {
114
+ throw new Error(
115
+ `Cannot read the vitest JSON report at ${reportPath}. A missing report means the run never produced one, which is itself proof the case did not execute. Cause: ${cause instanceof Error ? cause.message : String(cause)}`
116
+ );
117
+ }
118
+ const files = Array.isArray(parsed?.testResults) ? parsed.testResults : [];
119
+ return new Map(
120
+ files.flatMap(file =>
121
+ (Array.isArray(file?.assertionResults) ? file.assertionResults : []).map(
122
+ assertion => [
123
+ String(assertion?.fullName),
124
+ {
125
+ status: String(assertion?.status),
126
+ ...(typeof assertion?.duration === "number"
127
+ ? { duration: assertion.duration }
128
+ : {}),
129
+ },
130
+ ]
131
+ )
132
+ )
133
+ );
134
+ }
135
+
136
+ /**
137
+ * Explain why one named case does not count as executed, if it does not.
138
+ * @param {string} name - Full test name the lane claims to run
139
+ * @param {{status: string, duration?: number} | undefined} reported - Its report entry
140
+ * @param {readonly string[]} [available] - Every name the report did contain
141
+ * @returns {string | undefined} Operator-readable failure, or undefined when it ran
142
+ */
143
+ export function executionFailure(name, reported, available = []) {
144
+ if (reported === undefined)
145
+ return `"${name}" is ABSENT from the report — nothing in this lane ran it. Either its file was excluded, moved or renamed, or this name is written wrong: vitest's JSON reporter joins suite titles to the case title with a SPACE, while \`vitest list\` prints them with " > ". The report contained ${available.length === 0 ? "no cases at all" : available.map(reportedName => `"${reportedName}"`).join(", ")}.`;
146
+ if (reported.status !== "passed")
147
+ return `"${name}" did not execute: ${NON_EXECUTED_STATUS_ADVICE.get(reported.status) ?? `the runner reported status "${reported.status}"`}.`;
148
+ if (typeof reported.duration !== "number" || reported.duration <= 0)
149
+ return `"${name}" is reported as passed but consumed no measurable time, so there is no evidence it did any work.`;
150
+ return undefined;
151
+ }
152
+
153
+ /**
154
+ * Prove every named case executed, printing the measured time for each.
155
+ * @param {readonly string[]} argv - Arguments after the script path
156
+ * @returns {readonly string[]} Failures, empty when every case executed
157
+ */
158
+ export function checkTestCasesExecuted(argv) {
159
+ const { names, report } = parseArguments(argv);
160
+ const cases = reportedCases(report);
161
+ const available = [...cases.keys()];
162
+ return names.flatMap(name => {
163
+ const failure = executionFailure(name, cases.get(name), available);
164
+ if (failure !== undefined) return [failure];
165
+ process.stdout.write(
166
+ `EXECUTED ${name} — ${(cases.get(name)?.duration ?? 0).toFixed(1)}ms\n`
167
+ );
168
+ return [];
169
+ });
170
+ }
171
+
172
+ if (invokedAsScript(import.meta.url)) {
173
+ try {
174
+ const failures = checkTestCasesExecuted(process.argv.slice(2));
175
+ for (const failure of failures)
176
+ process.stderr.write(`NOT EXECUTED ${failure}\n`);
177
+ process.exit(failures.length === 0 ? 0 : 1);
178
+ } catch (error) {
179
+ process.stderr.write(
180
+ `${error instanceof Error ? error.message : String(error)}\n`
181
+ );
182
+ process.exit(1);
183
+ }
184
+ }