@codyswann/lisa 3.69.5 → 3.69.6
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.
- package/all/copy-overwrite/scripts/lisa-gates.mjs +112 -11
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +9 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +8 -7
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/copy-overwrite/scripts/bdd/contract.mjs +41 -2
- package/expo/copy-overwrite/scripts/bdd/envelope.mjs +18 -68
- package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +135 -206
- package/expo/create-only/bdd/coverage-map.json +1 -7
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/scripts/check-learnings-budget.ts +93 -18
- package/typescript/github-rulesets/quality-checks.json +4 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.69.
|
|
3
|
+
"version": "3.69.6",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.69.
|
|
3
|
+
"version": "3.69.6",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.69.
|
|
3
|
+
"version": "3.69.6",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.69.
|
|
3
|
+
"version": "3.69.6",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.69.
|
|
3
|
+
"version": "3.69.6",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* CI gate for the canonical project learnings document and its hard budgets.
|
|
3
|
+
*
|
|
4
|
+
* With ONE argument it checks that file and nothing else, which is what the
|
|
5
|
+
* `📚 Learnings Budget` job's consumer path uses.
|
|
6
|
+
*
|
|
7
|
+
* With ZERO arguments it checks TWO files: the shipped template, and this
|
|
8
|
+
* repository's own ledger resolved the way the contract resolves it. It used to
|
|
9
|
+
* check only the template — 0 entries, so it passed unconditionally — which
|
|
10
|
+
* made `bun run check:learnings-budget` look like a gate on the ledger and act
|
|
11
|
+
* like a gate on nothing. The quality job worked around that by passing the
|
|
12
|
+
* resolved path explicitly, and the comment there said so out loud: "passing
|
|
13
|
+
* the real path explicitly is what keeps this a gate and not a silent no-op."
|
|
14
|
+
* A default whose only safe use is not using it is a trap, so the default now
|
|
15
|
+
* covers both surfaces and the workaround is no longer load-bearing (#2932).
|
|
16
|
+
*
|
|
17
|
+
* The two surfaces are genuinely different and both matter: the template is
|
|
18
|
+
* what every adopting project starts from, and the ledger is what this
|
|
19
|
+
* repository's agents actually read. A missing template is a failure — it is
|
|
20
|
+
* committed here and always exists. A missing ledger is a pass, because a
|
|
21
|
+
* project that has never recorded a learning has no file.
|
|
22
|
+
* @module scripts/check-learnings-budget
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
25
|
import * as path from "node:path";
|
|
4
26
|
import { pathToFileURL } from "node:url";
|
|
5
27
|
import type * as BudgetCheckModule from "../src/core/learnings-budget-check.js";
|
|
@@ -9,15 +31,44 @@ type BudgetChecker = Pick<
|
|
|
9
31
|
"checkLearningsBudget" | "formatDiagnosticPath"
|
|
10
32
|
>;
|
|
11
33
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
34
|
+
const REPO_ROOT = path.resolve(import.meta.dir, "..");
|
|
35
|
+
|
|
36
|
+
const TEMPLATE_LEARNINGS_FILE = path.resolve(
|
|
37
|
+
REPO_ROOT,
|
|
15
38
|
"all",
|
|
16
39
|
"create-only",
|
|
17
40
|
".lisa",
|
|
18
41
|
"PROJECT_LEARNINGS.md"
|
|
19
42
|
);
|
|
20
43
|
|
|
44
|
+
/** Where the contract puts a project's ledger when nothing overrides it. */
|
|
45
|
+
const DEFAULT_LEDGER_RELATIVE = path.join(".lisa", "PROJECT_LEARNINGS.md");
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This repository's own ledger, resolved the way the contract resolves it.
|
|
49
|
+
*
|
|
50
|
+
* Reads `learnings.file` from `.lisa.config.json` and falls back to the
|
|
51
|
+
* documented default. Resolving it here rather than writing the path into a
|
|
52
|
+
* workflow is what stops the two drifting: an override would otherwise move the
|
|
53
|
+
* ledger and leave every caller checking a file that no longer exists.
|
|
54
|
+
* @returns Absolute path to the ledger, whether or not it exists
|
|
55
|
+
*/
|
|
56
|
+
function resolveLedger(): string {
|
|
57
|
+
const configPath = path.join(REPO_ROOT, ".lisa.config.json");
|
|
58
|
+
const override = existsSync(configPath)
|
|
59
|
+
? (
|
|
60
|
+
JSON.parse(readFileSync(configPath, "utf8")) as {
|
|
61
|
+
learnings?: { file?: unknown };
|
|
62
|
+
}
|
|
63
|
+
).learnings?.file
|
|
64
|
+
: undefined;
|
|
65
|
+
const relative =
|
|
66
|
+
typeof override === "string" && override.trim() !== ""
|
|
67
|
+
? override
|
|
68
|
+
: DEFAULT_LEDGER_RELATIVE;
|
|
69
|
+
return path.resolve(REPO_ROOT, relative);
|
|
70
|
+
}
|
|
71
|
+
|
|
21
72
|
/** Run the package-facing checker with zero or one explicit file path. */
|
|
22
73
|
async function main(): Promise<void> {
|
|
23
74
|
const arguments_ = process.argv.slice(2);
|
|
@@ -25,25 +76,49 @@ async function main(): Promise<void> {
|
|
|
25
76
|
fail("Usage: bun run check:learnings-budget -- [PROJECT_LEARNINGS.md]");
|
|
26
77
|
}
|
|
27
78
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
:
|
|
79
|
+
const checker = await loadBudgetChecker();
|
|
80
|
+
if (arguments_.length === 1) {
|
|
81
|
+
await check(checker, path.resolve(process.cwd(), arguments_[0] as string), {
|
|
82
|
+
absenceIsFailure: true,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
await check(checker, TEMPLATE_LEARNINGS_FILE, { absenceIsFailure: true });
|
|
88
|
+
const ledger = resolveLedger();
|
|
89
|
+
if (!existsSync(ledger)) {
|
|
90
|
+
console.log(`${checker.formatDiagnosticPath(ledger)}: no learnings file`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await check(checker, ledger, { absenceIsFailure: true });
|
|
94
|
+
}
|
|
32
95
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Check one file and report, failing the process on any violation.
|
|
98
|
+
* @param checker - The loaded budget checker
|
|
99
|
+
* @param file - Absolute path to the document to check
|
|
100
|
+
* @param options - Whether a missing file is a violation
|
|
101
|
+
* @param options.absenceIsFailure - True when the file must exist
|
|
102
|
+
*/
|
|
103
|
+
async function check(
|
|
104
|
+
checker: BudgetChecker,
|
|
105
|
+
file: string,
|
|
106
|
+
options: { absenceIsFailure: boolean }
|
|
107
|
+
): Promise<void> {
|
|
108
|
+
const result = await checker.checkLearningsBudget(file);
|
|
36
109
|
if (result.kind === "ok") {
|
|
37
110
|
console.log(
|
|
38
|
-
`${formatDiagnosticPath(file)}: learnings budget passed (${result.entryCount}/${result.maxEntries} entries, ${result.measuredTokens}/${result.maxTokens} maxTokens)`
|
|
111
|
+
`${checker.formatDiagnosticPath(file)}: learnings budget passed (${result.entryCount}/${result.maxEntries} entries, ${result.measuredTokens}/${result.maxTokens} maxTokens)`
|
|
39
112
|
);
|
|
40
113
|
return;
|
|
41
114
|
}
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
115
|
+
// Both files this script checks are committed here, so a missing one is as
|
|
116
|
+
// much a failure as any other violation. Host projects use the
|
|
117
|
+
// `lisa check-learnings-budget` CLI subcommand instead, which treats a
|
|
118
|
+
// missing file as an expected pass.
|
|
119
|
+
if (options.absenceIsFailure) {
|
|
120
|
+
fail(`${checker.formatDiagnosticPath(file)}: ${result.detail}`);
|
|
121
|
+
}
|
|
47
122
|
}
|
|
48
123
|
|
|
49
124
|
/**
|