@codyswann/lisa 4.55.4 → 4.55.5
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/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +3 -2
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/copy-overwrite/scripts/bdd/validate.mjs +84 -8
- package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +1 -1
- package/package.json +4 -4
- 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
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
14
|
|
|
15
15
|
import { byCodeUnit, runnersByPlatform } from "./contract.mjs";
|
|
16
|
+
import { isDisclosed } from "./discover.mjs";
|
|
16
17
|
import { resolveInsideRepo } from "./parse.mjs";
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -183,10 +184,19 @@ function orphanReason(reference, { keys, repos, defaultRepo }) {
|
|
|
183
184
|
: `unknown repo ${repo}; declare it in trackers.github.repos`;
|
|
184
185
|
}
|
|
185
186
|
|
|
187
|
+
/**
|
|
188
|
+
* An empty discovery result, for callers that do not walk the tree.
|
|
189
|
+
*
|
|
190
|
+
* A caller that supplies no discovery gets exactly the findings it got before
|
|
191
|
+
* the rename hint existed. Absent discovery must read as "nothing to pair
|
|
192
|
+
* with", never as "pair with whatever is at hand".
|
|
193
|
+
*/
|
|
194
|
+
const NO_DISCOVERY = Object.freeze({ specs: [] });
|
|
195
|
+
|
|
186
196
|
/**
|
|
187
197
|
* Validate every scenario→test mapping, including that its evidence still
|
|
188
198
|
* exists inside the mapped file.
|
|
189
|
-
* @param {object} input - Root, scenarios,
|
|
199
|
+
* @param {object} input - Root, scenarios, the parsed contract, and discovery.
|
|
190
200
|
* @returns {object[]} Defects found.
|
|
191
201
|
*/
|
|
192
202
|
export function validateMappings({
|
|
@@ -194,6 +204,7 @@ export function validateMappings({
|
|
|
194
204
|
scenarios,
|
|
195
205
|
contract,
|
|
196
206
|
cache = new Map(),
|
|
207
|
+
discovery = NO_DISCOVERY,
|
|
197
208
|
}) {
|
|
198
209
|
const byId = new Map(scenarios.map(scenario => [scenario.id, scenario]));
|
|
199
210
|
const platformRunners = runnersByPlatform(contract.runnerPlatforms);
|
|
@@ -216,7 +227,9 @@ export function validateMappings({
|
|
|
216
227
|
}
|
|
217
228
|
defects.push(...mappingDuplicates(mapping, at, seen));
|
|
218
229
|
defects.push(...mappingPlatforms(mapping, scenario, platformRunners, at));
|
|
219
|
-
defects.push(
|
|
230
|
+
defects.push(
|
|
231
|
+
...mappingEvidence({ root, mapping, at, cache, contract, discovery })
|
|
232
|
+
);
|
|
220
233
|
}
|
|
221
234
|
return defects;
|
|
222
235
|
}
|
|
@@ -327,6 +340,11 @@ export function evidenceResolves(root, mapping, cache = new Map()) {
|
|
|
327
340
|
return {
|
|
328
341
|
ok: false,
|
|
329
342
|
code: "mapping-evidence",
|
|
343
|
+
// The ONE verdict a rename could explain: a live file that used to carry
|
|
344
|
+
// this string. A mapping with no evidence at all and a mapped file that
|
|
345
|
+
// is gone both return above, unmarked, so neither can be dressed up as
|
|
346
|
+
// a rename by a caller reading only the code.
|
|
347
|
+
stale: true,
|
|
330
348
|
detail: `${mapping.file} no longer contains ${JSON.stringify(mapping.evidence)}`,
|
|
331
349
|
};
|
|
332
350
|
}
|
|
@@ -357,19 +375,77 @@ export function unresolvedEvidenceKeys({ root, contract, cache = new Map() }) {
|
|
|
357
375
|
);
|
|
358
376
|
}
|
|
359
377
|
|
|
378
|
+
/**
|
|
379
|
+
* The titles in the MAPPED FILE that nothing in the contract accounts for.
|
|
380
|
+
*
|
|
381
|
+
* Scoped to `mapping.file` and to nothing else. A title in a sibling file is
|
|
382
|
+
* never a candidate: pairing across files would let one deletion here and one
|
|
383
|
+
* addition anywhere in the repository read as a single rename, which is a
|
|
384
|
+
* confident wrong answer rather than a missing one.
|
|
385
|
+
*
|
|
386
|
+
* `isDisclosed` is asked with the WHOLE contract, this stale mapping included,
|
|
387
|
+
* so a new title that the dead evidence string happens to contain reads as
|
|
388
|
+
* accounted for and yields no candidate. That is the conservative direction:
|
|
389
|
+
* the hint goes quiet rather than offering a title something already claims.
|
|
390
|
+
* @param {object} mapping - Raw mapping entry.
|
|
391
|
+
* @param {object} contract - Parsed coverage map.
|
|
392
|
+
* @param {object} discovery - The discovery result.
|
|
393
|
+
* @returns {string[]} Candidate titles, deduplicated and ordered.
|
|
394
|
+
*/
|
|
395
|
+
function renameCandidates(mapping, contract, discovery) {
|
|
396
|
+
const unaccounted = (discovery.specs ?? [])
|
|
397
|
+
.filter(spec => spec.file === mapping.file)
|
|
398
|
+
.filter(
|
|
399
|
+
spec => typeof spec.evidence === "string" && spec.evidence.length > 0
|
|
400
|
+
)
|
|
401
|
+
.filter(spec => !isDisclosed(spec, contract))
|
|
402
|
+
.map(spec => spec.evidence);
|
|
403
|
+
return [...new Set(unaccounted)].sort(byCodeUnit);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Say a rename is the likely story, without ever picking which one.
|
|
408
|
+
*
|
|
409
|
+
* Every candidate is offered. Naming one would be a guess, and a confident
|
|
410
|
+
* wrong guess costs more than an honest list: the author knows which of their
|
|
411
|
+
* own tests moved and only needs to be told the two findings are one edit.
|
|
412
|
+
*
|
|
413
|
+
* Each title is JSON-quoted INDIVIDUALLY, so a title containing the comma the
|
|
414
|
+
* list joins on stays recoverable rather than splitting into two titles that
|
|
415
|
+
* were never in the file.
|
|
416
|
+
* @param {readonly string[]} candidates - Unaccounted titles in the same file.
|
|
417
|
+
* @returns {string} The hint, or the empty string when there is nothing to say.
|
|
418
|
+
*/
|
|
419
|
+
function renameHint(candidates) {
|
|
420
|
+
if (candidates.length === 0) return "";
|
|
421
|
+
const noun = candidates.length === 1 ? "title" : "titles";
|
|
422
|
+
return (
|
|
423
|
+
` — probably a rename: ${candidates.length} test ${noun} in that same` +
|
|
424
|
+
` file ${candidates.length === 1 ? "is" : "are"} named by no mapping and` +
|
|
425
|
+
` no exclusion. Candidates, each quoted whole:` +
|
|
426
|
+
` ${candidates.map(title => JSON.stringify(title)).join(", ")}.` +
|
|
427
|
+
` Re-point this mapping's evidence at the right one, or record an exclusion.`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
360
431
|
/**
|
|
361
432
|
* Prove the mapped file still contains the exact evidence string.
|
|
362
433
|
*
|
|
363
434
|
* This is what makes a mapping falsifiable rather than an assertion: rename
|
|
364
435
|
* or delete the test and the map breaks loudly instead of leaving a scenario
|
|
365
436
|
* silently unguarded.
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
437
|
+
*
|
|
438
|
+
* The hint appended here is MESSAGE ONLY. It never reaches `evidenceResolves`,
|
|
439
|
+
* which is what coverage counts from, so a renamed test stays a failure and
|
|
440
|
+
* stays uncovered until someone actually updates the map.
|
|
441
|
+
* @param {object} input - Root, the mapping, its label, the cache, the contract, and discovery.
|
|
370
442
|
* @returns {object[]} Defects found.
|
|
371
443
|
*/
|
|
372
|
-
function mappingEvidence(root, mapping, at, cache) {
|
|
444
|
+
function mappingEvidence({ root, mapping, at, cache, contract, discovery }) {
|
|
373
445
|
const verdict = evidenceResolves(root, mapping, cache);
|
|
374
|
-
|
|
446
|
+
if (verdict.ok) return [];
|
|
447
|
+
const hint = verdict.stale
|
|
448
|
+
? renameHint(renameCandidates(mapping, contract, discovery))
|
|
449
|
+
: "";
|
|
450
|
+
return [defect(verdict.code, `${at}: ${verdict.detail}${hint}`)];
|
|
375
451
|
}
|
|
@@ -248,7 +248,7 @@ function validateAll({
|
|
|
248
248
|
const defects = [
|
|
249
249
|
...validateScenarios(scenarios, platforms),
|
|
250
250
|
...validateTrackerTags(scenarios, contract.trackers),
|
|
251
|
-
...validateMappings({ root, scenarios, contract, cache }),
|
|
251
|
+
...validateMappings({ root, scenarios, contract, cache, discovery }),
|
|
252
252
|
...validateWaivers({ scenarios, contract, today: options.today }),
|
|
253
253
|
...discovery.defects,
|
|
254
254
|
...disclosureDefects({ root, contract, discovery }),
|
package/package.json
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"zod-validation-error": "^4.0.0"
|
|
188
188
|
},
|
|
189
189
|
"name": "@codyswann/lisa",
|
|
190
|
-
"version": "4.55.
|
|
190
|
+
"version": "4.55.5",
|
|
191
191
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
192
192
|
"main": "dist/index.js",
|
|
193
193
|
"exports": {
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
"test": "tests"
|
|
337
337
|
},
|
|
338
338
|
"types": "./dist/index.d.ts",
|
|
339
|
-
"lisaReleaseCommit": "
|
|
340
|
-
"gitHead": "
|
|
341
|
-
"lisaReleaseTag": "v4.55.
|
|
339
|
+
"lisaReleaseCommit": "3b91f194a303d3756679b63a137eeb74b8699930",
|
|
340
|
+
"gitHead": "3b91f194a303d3756679b63a137eeb74b8699930",
|
|
341
|
+
"lisaReleaseTag": "v4.55.5"
|
|
342
342
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.5",
|
|
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": "4.55.
|
|
3
|
+
"version": "4.55.5",
|
|
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": "4.55.
|
|
3
|
+
"version": "4.55.5",
|
|
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": "4.55.
|
|
3
|
+
"version": "4.55.5",
|
|
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": "4.55.
|
|
3
|
+
"version": "4.55.5",
|
|
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"
|