@codyswann/lisa 3.56.0 → 3.58.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.
- package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +92 -5
- package/all/copy-overwrite/scripts/lisa-gates.mjs +9 -19
- package/all/copy-overwrite/scripts/lisa-reconcile-policy.mjs +4 -4
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +12 -2
- package/dist/cli/ui-ci-quality-jobs-compute.js +2 -2
- package/dist/cli/ui-ci-quality-jobs-compute.js.map +1 -1
- package/dist/cli/ui-github-repo-expected.js +1 -1
- package/dist/cli/ui-github-repo-expected.js.map +1 -1
- 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 +14 -12
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/copy-overwrite/scripts/bdd/baseline.mjs +36 -45
- package/expo/copy-overwrite/scripts/bdd/render.mjs +1 -1
- package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +0 -6
- 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/.codex-plugin/skills/lisa-setup-sonar/SKILL.md +1 -1
- package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +3 -3
- package/plugins/lisa/skills/lisa-setup-sonar/SKILL.md +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-setup-sonar/SKILL.md +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-copilot/rules/reference/bdd-e2e-coverage.md +3 -3
- package/plugins/lisa-copilot/skills/lisa-setup-sonar/SKILL.md +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +3 -3
- package/plugins/lisa-cursor/skills/lisa-setup-sonar/SKILL.md +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/plugins/src/base/rules/reference/bdd-e2e-coverage.md +3 -3
- package/plugins/src/base/skills/lisa-setup-sonar/SKILL.md +1 -1
- package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +13 -6
- package/typescript/create-only/.github/required-checks.json +1 -1
- package/ui/index.html +2 -2
|
@@ -41,9 +41,6 @@ const defect = (code, message) => ({ code, message });
|
|
|
41
41
|
/** Defect / evidence code, named once. */
|
|
42
42
|
const SCENARIO_DELETED = "scenario-deleted";
|
|
43
43
|
|
|
44
|
-
/** The maintainer-applied PR label that authorizes giving coverage back. */
|
|
45
|
-
export const BASELINE_LABEL = "bdd-floor-baseline";
|
|
46
|
-
|
|
47
44
|
/**
|
|
48
45
|
* Fixed absolute locations git is installed at, tried before anything on PATH.
|
|
49
46
|
*
|
|
@@ -301,15 +298,23 @@ const RETIREMENT_FIELDS = ["reason", "ticket", "approvedBy", "recordedAt"];
|
|
|
301
298
|
|
|
302
299
|
/**
|
|
303
300
|
* Whether a scenario has been retired the way the contract requires: a
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
301
|
+
* COMPLETE `retirements` record.
|
|
302
|
+
*
|
|
303
|
+
* This used to also demand a maintainer-applied PR label, on the reasoning that
|
|
304
|
+
* two artifacts one author cannot produce alone is a stronger guarantee than
|
|
305
|
+
* one. The label was dropped because it guarantees the wrong thing: it verifies
|
|
306
|
+
* that a second person clicked, not that the behavior is actually gone, and it
|
|
307
|
+
* stalls the case it was most needed for — an agent retiring coverage for a
|
|
308
|
+
* feature the product genuinely no longer has.
|
|
309
|
+
*
|
|
310
|
+
* The record is the part that carries information. It still owes every field in
|
|
311
|
+
* {@link RETIREMENT_FIELDS}, is still refused when incomplete, and still lands
|
|
312
|
+
* in the diff where it can be read and challenged.
|
|
307
313
|
* @param {object|undefined} record - The retirements entry, if any.
|
|
308
|
-
* @
|
|
309
|
-
* @returns {boolean} True when the retirement is authorized and complete.
|
|
314
|
+
* @returns {boolean} True when the retirement is complete.
|
|
310
315
|
*/
|
|
311
|
-
function isRetired(record
|
|
312
|
-
if (!record
|
|
316
|
+
function isRetired(record) {
|
|
317
|
+
if (!record) return false;
|
|
313
318
|
return RETIREMENT_FIELDS.every(field => Boolean(record[field]));
|
|
314
319
|
}
|
|
315
320
|
|
|
@@ -324,15 +329,10 @@ function isRetired(record, labels) {
|
|
|
324
329
|
* Keys whose scenario disappeared from the contract entirely are left to
|
|
325
330
|
* {@link checkDeletions}, which names that act precisely; reporting both would
|
|
326
331
|
* describe one deletion as two different failures.
|
|
327
|
-
* @param {object} input - Baseline, head contract and scenarios
|
|
332
|
+
* @param {object} input - Baseline, and head contract and scenarios.
|
|
328
333
|
* @returns {object[]} Defects found.
|
|
329
334
|
*/
|
|
330
|
-
export function checkCoverageRegression({
|
|
331
|
-
baseline,
|
|
332
|
-
contract,
|
|
333
|
-
scenarios,
|
|
334
|
-
labels,
|
|
335
|
-
}) {
|
|
335
|
+
export function checkCoverageRegression({ baseline, contract, scenarios }) {
|
|
336
336
|
const before = acceptedKeys(baseline.scenarios, baseline.contract);
|
|
337
337
|
const after = acceptedKeys(scenarios, contract);
|
|
338
338
|
const present = new Set(scenarios.map(scenario => scenario.id));
|
|
@@ -343,42 +343,42 @@ export function checkCoverageRegression({
|
|
|
343
343
|
return [...before]
|
|
344
344
|
.filter(key => !after.has(key) && present.has(partsOf(key).scenario))
|
|
345
345
|
.sort(byCodeUnit)
|
|
346
|
-
.flatMap(key => regressionDefect(key, { retired, waived
|
|
346
|
+
.flatMap(key => regressionDefect(key, { retired, waived }));
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
/**
|
|
350
350
|
* The defect for one obligation whose accepted coverage disappeared, or none
|
|
351
351
|
* when it left the denominator through an authorized route.
|
|
352
352
|
* @param {string} key - The `SCENARIO:platform` key.
|
|
353
|
-
* @param {object} input - Retirement records
|
|
353
|
+
* @param {object} input - Retirement records and waived keys.
|
|
354
354
|
* @returns {object[]} Zero or one defect.
|
|
355
355
|
*/
|
|
356
|
-
function regressionDefect(key, { retired, waived
|
|
356
|
+
function regressionDefect(key, { retired, waived }) {
|
|
357
357
|
const { scenario, platform } = partsOf(key);
|
|
358
|
-
if (isRetired(retired.get(scenario)
|
|
359
|
-
if (waived.has(key)
|
|
358
|
+
if (isRetired(retired.get(scenario))) return [];
|
|
359
|
+
if (waived.has(key)) return [];
|
|
360
360
|
return [
|
|
361
361
|
defect(
|
|
362
362
|
"coverage-regression",
|
|
363
|
-
`${scenario}:${platform} was covered at the base revision and is not covered here. Coverage this repository already accepted cannot be handed back quietly. Restore the mapping, or take one of the two recorded routes out — a retirements record (${RETIREMENT_FIELDS.join(", ")}) for a behavior the product no longer has, or a platformWaivers entry for a runner that cannot decide it
|
|
363
|
+
`${scenario}:${platform} was covered at the base revision and is not covered here. Coverage this repository already accepted cannot be handed back quietly. Restore the mapping, or take one of the two recorded routes out — a retirements record (${RETIREMENT_FIELDS.join(", ")}) for a behavior the product no longer has, or a platformWaivers entry for a runner that cannot decide it. ${routeTaken(key, { retired })}`
|
|
364
364
|
),
|
|
365
365
|
];
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
/**
|
|
369
|
-
* Say
|
|
370
|
-
*
|
|
369
|
+
* Say what is missing from the authorization, so the operator is told what to
|
|
370
|
+
* do rather than only what went wrong.
|
|
371
|
+
*
|
|
372
|
+
* Only reached for a key that took NEITHER route: {@link regressionDefect}
|
|
373
|
+
* returns early for a waived one, so the waiver set cannot inform this
|
|
374
|
+
* sentence and is not passed.
|
|
371
375
|
* @param {string} key - The `SCENARIO:platform` key.
|
|
372
|
-
* @param {object} input - Retirement records
|
|
376
|
+
* @param {object} input - Retirement records.
|
|
373
377
|
* @returns {string} A one-sentence next step.
|
|
374
378
|
*/
|
|
375
|
-
function routeTaken(key, { retired
|
|
379
|
+
function routeTaken(key, { retired }) {
|
|
376
380
|
const { scenario } = partsOf(key);
|
|
377
381
|
const record = retired.get(scenario);
|
|
378
|
-
const authorized = labels.includes(BASELINE_LABEL);
|
|
379
|
-
if ((record || waived.has(key)) && !authorized) {
|
|
380
|
-
return `A record is present but the "${BASELINE_LABEL}" label is not: recording a reduction in the same pull request that makes it is not an authorization.`;
|
|
381
|
-
}
|
|
382
382
|
if (record) {
|
|
383
383
|
const missing = RETIREMENT_FIELDS.filter(field => !record[field]);
|
|
384
384
|
return `Its retirements record is incomplete (no ${missing.join(", no ")}).`;
|
|
@@ -419,10 +419,10 @@ export function checkNewObligations({ baseline, contract, scenarios }) {
|
|
|
419
419
|
* The contract's answer to a retired behavior is `@superseded`, which keeps
|
|
420
420
|
* the audit trail. Deleting the scenario instead makes coverage look better
|
|
421
421
|
* by describing less of the product.
|
|
422
|
-
* @param {object} input - Base IDs
|
|
422
|
+
* @param {object} input - Base IDs and head scenarios.
|
|
423
423
|
* @returns {object[]} Defects found.
|
|
424
424
|
*/
|
|
425
|
-
export function checkDeletions({ baseIds, scenarios, contract
|
|
425
|
+
export function checkDeletions({ baseIds, scenarios, contract }) {
|
|
426
426
|
const present = new Set(scenarios.map(scenario => scenario.id));
|
|
427
427
|
const retired = new Map(
|
|
428
428
|
(contract.retirements ?? []).map(entry => [entry.scenario, entry])
|
|
@@ -430,22 +430,21 @@ export function checkDeletions({ baseIds, scenarios, contract, labels }) {
|
|
|
430
430
|
return [...baseIds]
|
|
431
431
|
.filter(id => !present.has(id))
|
|
432
432
|
.sort(byCodeUnit)
|
|
433
|
-
.flatMap(id => deletionDefects(id, retired.get(id)
|
|
433
|
+
.flatMap(id => deletionDefects(id, retired.get(id)));
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
/**
|
|
437
437
|
* Defects for one deleted scenario.
|
|
438
438
|
* @param {string} id - The scenario ID that disappeared.
|
|
439
439
|
* @param {object|undefined} record - Its retirement record, if any.
|
|
440
|
-
* @param {readonly string[]} labels - PR labels.
|
|
441
440
|
* @returns {object[]} Defects found.
|
|
442
441
|
*/
|
|
443
|
-
function deletionDefects(id, record
|
|
442
|
+
function deletionDefects(id, record) {
|
|
444
443
|
if (!record) {
|
|
445
444
|
return [
|
|
446
445
|
defect(
|
|
447
446
|
SCENARIO_DELETED,
|
|
448
|
-
`${id} was deleted from the contract. Retiring a behavior is @superseded, not deletion — deleting it shrinks the denominator instead of the gap. A genuine removal needs a retirements record
|
|
447
|
+
`${id} was deleted from the contract. Retiring a behavior is @superseded, not deletion — deleting it shrinks the denominator instead of the gap. A genuine removal needs a complete retirements record (${RETIREMENT_FIELDS.join(", ")}).`
|
|
449
448
|
),
|
|
450
449
|
];
|
|
451
450
|
}
|
|
@@ -453,13 +452,5 @@ function deletionDefects(id, record, labels) {
|
|
|
453
452
|
const defects = missing.map(field =>
|
|
454
453
|
defect(SCENARIO_DELETED, `${id}: retirements record has no ${field}`)
|
|
455
454
|
);
|
|
456
|
-
if (!labels.includes(BASELINE_LABEL)) {
|
|
457
|
-
defects.push(
|
|
458
|
-
defect(
|
|
459
|
-
SCENARIO_DELETED,
|
|
460
|
-
`${id}: a retirement needs the maintainer-applied "${BASELINE_LABEL}" label`
|
|
461
|
-
)
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
455
|
return defects;
|
|
465
456
|
}
|
|
@@ -208,7 +208,7 @@ ${executionSection(report)}
|
|
|
208
208
|
|
|
209
209
|
## Coverage floor
|
|
210
210
|
|
|
211
|
-
The committed floor is an absolute bar — "is this platform below it right now" — and nothing else. It is **not** a ratchet and nobody has to nudge it upward: what protects coverage already earned is a separate, per-obligation check. Coverage accepted at the base revision cannot disappear, and behavior that is new must arrive mapped or waived; either reduction takes a recorded route
|
|
211
|
+
The committed floor is an absolute bar — "is this platform below it right now" — and nothing else. It is **not** a ratchet and nobody has to nudge it upward: what protects coverage already earned is a separate, per-obligation check. Coverage accepted at the base revision cannot disappear, and behavior that is new must arrive mapped or waived; either reduction takes a recorded route — a complete \`retirements\` record or a \`platformWaivers\` entry — which lands in the diff where it can be read and challenged.
|
|
212
212
|
|
|
213
213
|
${floorTable(report)}
|
|
214
214
|
|
|
@@ -312,14 +312,12 @@ function validateAll({
|
|
|
312
312
|
baseline,
|
|
313
313
|
contract,
|
|
314
314
|
scenarios,
|
|
315
|
-
labels: options.labels,
|
|
316
315
|
}),
|
|
317
316
|
...checkNewObligations({ baseline, contract, scenarios }),
|
|
318
317
|
...checkDeletions({
|
|
319
318
|
baseIds: baseline.scenarioIds,
|
|
320
319
|
scenarios,
|
|
321
320
|
contract,
|
|
322
|
-
labels: options.labels,
|
|
323
321
|
}),
|
|
324
322
|
];
|
|
325
323
|
}
|
|
@@ -679,10 +677,6 @@ export function parseArgs(argv, env) {
|
|
|
679
677
|
report: argv.includes("--report"),
|
|
680
678
|
resultFiles,
|
|
681
679
|
baseSha: env.BDD_BASE_SHA || null,
|
|
682
|
-
labels: (env.BDD_PR_LABELS ?? "")
|
|
683
|
-
.split(",")
|
|
684
|
-
.map(item => item.trim())
|
|
685
|
-
.filter(Boolean),
|
|
686
680
|
today: env.BDD_TODAY || new Date().toISOString().slice(0, 10),
|
|
687
681
|
};
|
|
688
682
|
}
|
package/package.json
CHANGED
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"zod-validation-error": "^4.0.0"
|
|
142
142
|
},
|
|
143
143
|
"name": "@codyswann/lisa",
|
|
144
|
-
"version": "3.
|
|
144
|
+
"version": "3.58.0",
|
|
145
145
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
146
146
|
"main": "dist/index.js",
|
|
147
147
|
"exports": {
|
|
@@ -12,7 +12,7 @@ unattended factories run. It replaces Lisa's former hand-rolled SonarCloud REST
|
|
|
12
12
|
access with the vendor's official token-authed MCP, which is Lisa's single Sonar
|
|
13
13
|
substrate on both developer machines and headless cloud routines.
|
|
14
14
|
|
|
15
|
-
This does **not** touch the CI
|
|
15
|
+
This does **not** touch the CI static-security job in `quality.yml` or its
|
|
16
16
|
`SONAR_TOKEN` secret — that enforcement gate is separate and stays as-is.
|
|
17
17
|
|
|
18
18
|
## Supported agents
|
|
@@ -145,9 +145,9 @@ forces it upward, and lowering it needs no ceremony.
|
|
|
145
145
|
|
|
146
146
|
What stops coverage sliding backwards is checked directly, per obligation, against the base
|
|
147
147
|
revision — **an obligation that was mapped may not stop being mapped, and new behavior arrives
|
|
148
|
-
mapped or waived**. Giving coverage back is legitimate but takes
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
mapped or waived**. Giving coverage back is legitimate but takes a recorded route: a complete `retirements`
|
|
149
|
+
record (for a behavior the product no longer has) or a `platformWaivers` entry (for a runner
|
|
150
|
+
that cannot decide it). Gaps that predate the change are burndown, never a
|
|
151
151
|
gate failure — which is what lets a brownfield project adopt `enforced` without first backfilling
|
|
152
152
|
its whole history.
|
|
153
153
|
|
|
@@ -12,7 +12,7 @@ unattended factories run. It replaces Lisa's former hand-rolled SonarCloud REST
|
|
|
12
12
|
access with the vendor's official token-authed MCP, which is Lisa's single Sonar
|
|
13
13
|
substrate on both developer machines and headless cloud routines.
|
|
14
14
|
|
|
15
|
-
This does **not** touch the CI
|
|
15
|
+
This does **not** touch the CI static-security job in `quality.yml` or its
|
|
16
16
|
`SONAR_TOKEN` secret — that enforcement gate is separate and stays as-is.
|
|
17
17
|
|
|
18
18
|
## Supported agents
|
|
@@ -12,7 +12,7 @@ unattended factories run. It replaces Lisa's former hand-rolled SonarCloud REST
|
|
|
12
12
|
access with the vendor's official token-authed MCP, which is Lisa's single Sonar
|
|
13
13
|
substrate on both developer machines and headless cloud routines.
|
|
14
14
|
|
|
15
|
-
This does **not** touch the CI
|
|
15
|
+
This does **not** touch the CI static-security job in `quality.yml` or its
|
|
16
16
|
`SONAR_TOKEN` secret — that enforcement gate is separate and stays as-is.
|
|
17
17
|
|
|
18
18
|
## Supported agents
|
|
@@ -145,9 +145,9 @@ forces it upward, and lowering it needs no ceremony.
|
|
|
145
145
|
|
|
146
146
|
What stops coverage sliding backwards is checked directly, per obligation, against the base
|
|
147
147
|
revision — **an obligation that was mapped may not stop being mapped, and new behavior arrives
|
|
148
|
-
mapped or waived**. Giving coverage back is legitimate but takes
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
mapped or waived**. Giving coverage back is legitimate but takes a recorded route: a complete `retirements`
|
|
149
|
+
record (for a behavior the product no longer has) or a `platformWaivers` entry (for a runner
|
|
150
|
+
that cannot decide it). Gaps that predate the change are burndown, never a
|
|
151
151
|
gate failure — which is what lets a brownfield project adopt `enforced` without first backfilling
|
|
152
152
|
its whole history.
|
|
153
153
|
|
|
@@ -12,7 +12,7 @@ unattended factories run. It replaces Lisa's former hand-rolled SonarCloud REST
|
|
|
12
12
|
access with the vendor's official token-authed MCP, which is Lisa's single Sonar
|
|
13
13
|
substrate on both developer machines and headless cloud routines.
|
|
14
14
|
|
|
15
|
-
This does **not** touch the CI
|
|
15
|
+
This does **not** touch the CI static-security job in `quality.yml` or its
|
|
16
16
|
`SONAR_TOKEN` secret — that enforcement gate is separate and stays as-is.
|
|
17
17
|
|
|
18
18
|
## Supported agents
|
|
@@ -150,9 +150,9 @@ forces it upward, and lowering it needs no ceremony.
|
|
|
150
150
|
|
|
151
151
|
What stops coverage sliding backwards is checked directly, per obligation, against the base
|
|
152
152
|
revision — **an obligation that was mapped may not stop being mapped, and new behavior arrives
|
|
153
|
-
mapped or waived**. Giving coverage back is legitimate but takes
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
mapped or waived**. Giving coverage back is legitimate but takes a recorded route: a complete `retirements`
|
|
154
|
+
record (for a behavior the product no longer has) or a `platformWaivers` entry (for a runner
|
|
155
|
+
that cannot decide it). Gaps that predate the change are burndown, never a
|
|
156
156
|
gate failure — which is what lets a brownfield project adopt `enforced` without first backfilling
|
|
157
157
|
its whole history.
|
|
158
158
|
|
|
@@ -12,7 +12,7 @@ unattended factories run. It replaces Lisa's former hand-rolled SonarCloud REST
|
|
|
12
12
|
access with the vendor's official token-authed MCP, which is Lisa's single Sonar
|
|
13
13
|
substrate on both developer machines and headless cloud routines.
|
|
14
14
|
|
|
15
|
-
This does **not** touch the CI
|
|
15
|
+
This does **not** touch the CI static-security job in `quality.yml` or its
|
|
16
16
|
`SONAR_TOKEN` secret — that enforcement gate is separate and stays as-is.
|
|
17
17
|
|
|
18
18
|
## Supported agents
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.58.0",
|
|
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.
|
|
3
|
+
"version": "3.58.0",
|
|
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.
|
|
3
|
+
"version": "3.58.0",
|
|
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.
|
|
3
|
+
"version": "3.58.0",
|
|
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.
|
|
3
|
+
"version": "3.58.0",
|
|
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"
|