@codyswann/lisa 4.25.3 → 4.26.1

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 (94) hide show
  1. package/dist/cli/check-learnings-budget-cmd.d.ts +2 -0
  2. package/dist/cli/check-learnings-budget-cmd.d.ts.map +1 -1
  3. package/dist/cli/check-learnings-budget-cmd.js +17 -6
  4. package/dist/cli/check-learnings-budget-cmd.js.map +1 -1
  5. package/dist/cli/gate-commands.d.ts +3 -1
  6. package/dist/cli/gate-commands.d.ts.map +1 -1
  7. package/dist/cli/gate-commands.js +5 -2
  8. package/dist/cli/gate-commands.js.map +1 -1
  9. package/dist/core/configured-learnings-path.d.ts +16 -0
  10. package/dist/core/configured-learnings-path.d.ts.map +1 -0
  11. package/dist/core/configured-learnings-path.js +42 -0
  12. package/dist/core/configured-learnings-path.js.map +1 -0
  13. package/dist/core/learnings-budget-check.d.ts +13 -3
  14. package/dist/core/learnings-budget-check.d.ts.map +1 -1
  15. package/dist/core/learnings-budget-check.js +41 -10
  16. package/dist/core/learnings-budget-check.js.map +1 -1
  17. package/dist/core/learnings-overflow-path.d.ts +11 -0
  18. package/dist/core/learnings-overflow-path.d.ts.map +1 -0
  19. package/dist/core/learnings-overflow-path.js +19 -0
  20. package/dist/core/learnings-overflow-path.js.map +1 -0
  21. package/dist/core/learnings-overflow.d.ts +1 -11
  22. package/dist/core/learnings-overflow.d.ts.map +1 -1
  23. package/dist/core/learnings-overflow.js +2 -17
  24. package/dist/core/learnings-overflow.js.map +1 -1
  25. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  26. package/dist/core/lisa-owned-hash-ledger.js +12 -0
  27. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  28. package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts +4 -4
  29. package/dist/core/nightly-e2e-guard-behavior-certificate.js +7 -7
  30. package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
  31. package/dist/core/project-config.d.ts.map +1 -1
  32. package/dist/core/project-config.js +4 -38
  33. package/dist/core/project-config.js.map +1 -1
  34. package/dist/core/safe-relative-markdown-path.d.ts +10 -0
  35. package/dist/core/safe-relative-markdown-path.d.ts.map +1 -0
  36. package/dist/core/safe-relative-markdown-path.js +42 -0
  37. package/dist/core/safe-relative-markdown-path.js.map +1 -0
  38. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  39. package/dist/core/upstream-evidence-manifest.js +9 -3
  40. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  41. package/package.json +3 -3
  42. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-agy/plugin.json +1 -1
  45. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  48. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-expo-agy/plugin.json +1 -1
  55. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  60. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  65. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  70. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  75. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  79. package/plugins/lisa-rails-agy/plugin.json +1 -1
  80. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  84. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  85. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  90. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  92. package/scripts/check-learnings-budget.ts +96 -22
  93. package/scripts/generate-nightly-e2e-guard-certificate.mjs +5 -0
  94. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +338 -39
@@ -32,6 +32,8 @@ import { existsSync, readFileSync } from "node:fs";
32
32
  import * as path from "node:path";
33
33
  import { pathToFileURL } from "node:url";
34
34
  import type * as BudgetCheckModule from "../src/core/learnings-budget-check.js";
35
+ import type * as ConfiguredPathModule from "../src/core/configured-learnings-path.js";
36
+ import type * as OverflowPathModule from "../src/core/learnings-overflow-path.js";
35
37
 
36
38
  type BudgetChecker = Pick<
37
39
  typeof BudgetCheckModule,
@@ -48,9 +50,6 @@ const TEMPLATE_LEARNINGS_FILE = path.resolve(
48
50
  "PROJECT_LEARNINGS.md"
49
51
  );
50
52
 
51
- /** Where the contract puts a project's ledger when nothing overrides it. */
52
- const DEFAULT_LEDGER_RELATIVE = path.join(".lisa", "PROJECT_LEARNINGS.md");
53
-
54
53
  /**
55
54
  * This repository's own ledger, resolved the way the contract resolves it.
56
55
  *
@@ -58,22 +57,26 @@ const DEFAULT_LEDGER_RELATIVE = path.join(".lisa", "PROJECT_LEARNINGS.md");
58
57
  * documented default. Resolving it here rather than writing the path into a
59
58
  * workflow is what stops the two drifting: an override would otherwise move the
60
59
  * ledger and leave every caller checking a file that no longer exists.
61
- * @returns Absolute path to the ledger, whether or not it exists
60
+ * @returns Project-relative path to the ledger, whether or not it exists
62
61
  */
63
- function resolveLedger(): string {
62
+ async function resolveLedgerRelative(): Promise<string> {
64
63
  const configPath = path.join(REPO_ROOT, ".lisa.config.json");
65
- const override = existsSync(configPath)
66
- ? (
67
- JSON.parse(readFileSync(configPath, "utf8")) as {
68
- learnings?: { file?: unknown };
69
- }
70
- ).learnings?.file
71
- : undefined;
72
- const relative =
73
- typeof override === "string" && override.trim() !== ""
74
- ? override
75
- : DEFAULT_LEDGER_RELATIVE;
76
- return path.resolve(REPO_ROOT, relative);
64
+ const resolver = await loadConfiguredLearningsResolver();
65
+ const parsed: unknown = existsSync(configPath)
66
+ ? JSON.parse(readFileSync(configPath, "utf8"))
67
+ : {};
68
+ return resolver(parsed, configPath);
69
+ }
70
+
71
+ /** Resolve this repository's configured ledger to an absolute path. */
72
+ async function resolveLedger(): Promise<string> {
73
+ return path.resolve(REPO_ROOT, await resolveLedgerRelative());
74
+ }
75
+
76
+ /** Resolve the configured ledger's sibling overflow through the shared rule. */
77
+ async function resolveOverflow(): Promise<string> {
78
+ const resolver = await loadOverflowResolver();
79
+ return path.resolve(REPO_ROOT, resolver(await resolveLedgerRelative()));
77
80
  }
78
81
 
79
82
  /**
@@ -96,14 +99,18 @@ function isSourceCheckout(): boolean {
96
99
  async function main(): Promise<void> {
97
100
  const arguments_ = process.argv.slice(2);
98
101
  if (arguments_.length > 1) {
99
- fail("Usage: bun run check:learnings-budget -- [PROJECT_LEARNINGS.md]");
102
+ fail(
103
+ "Usage: bun run check:learnings-budget -- [PROJECT_LEARNINGS.md | --overflow]"
104
+ );
100
105
  }
101
106
 
102
107
  const checker = await loadBudgetChecker();
103
108
  const inspected =
104
- arguments_.length === 1
105
- ? await checkExplicitSurface(checker, arguments_[0] as string)
106
- : await checkDefaultSurfaces(checker);
109
+ arguments_[0] === "--overflow"
110
+ ? await checkOverflowSurface(checker, await resolveOverflow())
111
+ : arguments_.length === 1
112
+ ? await checkExplicitSurface(checker, arguments_[0] as string)
113
+ : await checkDefaultSurfaces(checker);
107
114
 
108
115
  // VACUITY GUARD. Every path above either judges a document or exits, so this
109
116
  // should be unreachable — which is the point. A run that inspected nothing
@@ -119,6 +126,29 @@ async function main(): Promise<void> {
119
126
  }
120
127
  }
121
128
 
129
+ /** Check the optional overflow, whose absence is the expected empty state. */
130
+ async function checkOverflowSurface(
131
+ checker: BudgetChecker,
132
+ file: string
133
+ ): Promise<number> {
134
+ const result = await checker.checkLearningsBudget(file, {
135
+ surface: "overflow",
136
+ });
137
+ if (result.kind === "missing") {
138
+ console.log(
139
+ `no learnings overflow file at ${checker.formatDiagnosticPath(file)} — nothing to check`
140
+ );
141
+ return 1;
142
+ }
143
+ if (result.kind === "violation") {
144
+ fail(`${checker.formatDiagnosticPath(file)}: ${result.detail}`);
145
+ }
146
+ console.log(
147
+ checker.formatBudgetVerdict(file, result, { surface: "overflow" })
148
+ );
149
+ return 1;
150
+ }
151
+
122
152
  /**
123
153
  * Check the one document named on the command line.
124
154
  * @param checker - The loaded budget checker
@@ -141,7 +171,7 @@ async function checkExplicitSurface(
141
171
  */
142
172
  async function checkDefaultSurfaces(checker: BudgetChecker): Promise<number> {
143
173
  await check(checker, TEMPLATE_LEARNINGS_FILE);
144
- const ledger = resolveLedger();
174
+ const ledger = await resolveLedger();
145
175
  if (existsSync(ledger)) {
146
176
  await check(checker, ledger);
147
177
  return 2;
@@ -213,6 +243,50 @@ async function loadBudgetChecker(): Promise<BudgetChecker> {
213
243
  } as BudgetChecker;
214
244
  }
215
245
 
246
+ /** Load the pure overflow filename resolver from source or compiled package. */
247
+ async function loadOverflowResolver(): Promise<
248
+ typeof OverflowPathModule.resolveLearningsOverflowFile
249
+ > {
250
+ const packageRoot = path.resolve(import.meta.dir, "..");
251
+ const sourceTypescript = path.join(
252
+ packageRoot,
253
+ "src",
254
+ "core",
255
+ "learnings-overflow-path.ts"
256
+ );
257
+ const runtimeRoot = path.join(
258
+ packageRoot,
259
+ existsSync(sourceTypescript) ? "src" : "dist",
260
+ "core"
261
+ );
262
+ const module_ = (await import(
263
+ pathToFileURL(path.join(runtimeRoot, "learnings-overflow-path.js")).href
264
+ )) as typeof OverflowPathModule;
265
+ return module_.resolveLearningsOverflowFile;
266
+ }
267
+
268
+ /** Load the dependency-free configured learnings-path resolver. */
269
+ async function loadConfiguredLearningsResolver(): Promise<
270
+ typeof ConfiguredPathModule.resolveLearningsFileFromRawConfig
271
+ > {
272
+ const packageRoot = path.resolve(import.meta.dir, "..");
273
+ const sourceTypescript = path.join(
274
+ packageRoot,
275
+ "src",
276
+ "core",
277
+ "configured-learnings-path.ts"
278
+ );
279
+ const runtimeRoot = path.join(
280
+ packageRoot,
281
+ existsSync(sourceTypescript) ? "src" : "dist",
282
+ "core"
283
+ );
284
+ const module_ = (await import(
285
+ pathToFileURL(path.join(runtimeRoot, "configured-learnings-path.js")).href
286
+ )) as typeof ConfiguredPathModule;
287
+ return module_.resolveLearningsFileFromRawConfig;
288
+ }
289
+
216
290
  /** Print one deterministic failure diagnostic and exit non-zero. */
217
291
  function fail(message: string): never {
218
292
  console.error(`check:learnings-budget: ${message}`);
@@ -68,6 +68,11 @@ const validRequest = Object.freeze({
68
68
  const VERSION_EXPECTATIONS = Object.freeze({
69
69
  "1.1.0": Object.freeze({ selfService: "refused" }),
70
70
  "1.7.0": Object.freeze({ selfService: "valid" }),
71
+ // 1.8.0 changed SELECTION (which run the gate scores), not the waiver
72
+ // handler, so the bounded-waiver expectations are unchanged. The entry is
73
+ // still required: an unlisted contract version is refused rather than assumed
74
+ // to behave like its predecessor.
75
+ "1.8.0": Object.freeze({ selfService: "valid" }),
71
76
  });
72
77
 
73
78
  /**