@codyswann/lisa 3.1.0 → 3.2.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/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +28 -12
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/copy-overwrite/scripts/bdd/baseline.mjs +211 -121
- package/expo/copy-overwrite/scripts/bdd/contract.mjs +10 -2
- package/expo/copy-overwrite/scripts/bdd/envelope.mjs +3 -2
- package/expo/copy-overwrite/scripts/bdd/render.mjs +2 -2
- package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +45 -8
- package/expo/copy-overwrite/scripts/classify-maestro-failures.mjs +775 -0
- package/expo/create-only/.maestro/flake-classification.json +21 -0
- package/expo/create-only/bdd/coverage-map.json +1 -2
- package/expo/package-lisa/package.lisa.json +1 -0
- 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/hooks/threshold-ratchet-families.mjs +24 -0
- package/plugins/lisa/rules/eager/credential-substrate-precedence.md +52 -0
- package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +19 -8
- 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-copilot/hooks/threshold-ratchet-families.mjs +24 -0
- package/plugins/lisa-copilot/rules/eager/credential-substrate-precedence.md +52 -0
- package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +19 -8
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +24 -0
- package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +19 -8
- package/plugins/lisa-cursor/rules/credential-substrate-precedence.mdc +57 -0
- 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/hooks/threshold-ratchet-families.mjs +24 -0
- package/plugins/src/base/rules/eager/credential-substrate-precedence.md +52 -0
- package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +19 -8
- package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +24 -0
- package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +24 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.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.2.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.2.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.2.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.2.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"
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
* File families the ratchet watches. `kind` selects the extractor;
|
|
11
11
|
* `direction` applies to numeric-leaf kinds ("min" values may only rise,
|
|
12
12
|
* "max" values may only fall).
|
|
13
|
+
*
|
|
14
|
+
* PER-FAMILY POLICY, reviewed 2026-08-12. A family keeps its ratchet unless a
|
|
15
|
+
* NAMED deterministic non-regression invariant replaces the property the
|
|
16
|
+
* ratchet was providing — deleting a ratchet deletes that property with it, so
|
|
17
|
+
* "this generates churn" is a reason to find a replacement, never a reason to
|
|
18
|
+
* delete on its own:
|
|
19
|
+
*
|
|
20
|
+
* coverage / simplecov / e2e KEPT. Here the ratchet IS the non-regression
|
|
21
|
+
* invariant, and no per-item equivalent exists short of committing a
|
|
22
|
+
* per-file coverage baseline — an artifact that only ever accumulates.
|
|
23
|
+
* Revisit if one appears.
|
|
24
|
+
* stryker KEPT. `thresholds.break` is an absolute floor,
|
|
25
|
+
* kept outright; the mutate-list comparison detects EXEMPTION ADDITIONS
|
|
26
|
+
* rather than creep, and has no number for a pull request to nudge.
|
|
27
|
+
* eslint / rubocop / k6 / lisa-config KEPT, unchanged.
|
|
28
|
+
*
|
|
29
|
+
* Exactly one family was replaced, and it is not watched here and never was:
|
|
30
|
+
* the BDD traceability floor, whose numeric ratchet gave way to per-obligation
|
|
31
|
+
* checks. See `expo/copy-overwrite/scripts/bdd/baseline.mjs`.
|
|
32
|
+
*
|
|
33
|
+
* Retiring a family is SEQUENCED: the replacement invariant lands, then a
|
|
34
|
+
* `thresholdRatchet.allow` entry merges from the base side, then the mechanism
|
|
35
|
+
* changes. Never the reverse — this checker is precisely what stops a change
|
|
36
|
+
* granting itself the exception that permits it.
|
|
13
37
|
*/
|
|
14
38
|
export const FAMILIES = [
|
|
15
39
|
{
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Credential-Substrate Precedence (load-bearing)
|
|
2
|
+
|
|
3
|
+
**When more than one substrate can reach an external system, the configured credentials
|
|
4
|
+
provider's token/CLI path goes first and the interactive MCP is the fallback — and
|
|
5
|
+
identity-match verification is mandatory on every substrate, at every tier.**
|
|
6
|
+
|
|
7
|
+
**One shared, vendor-neutral contract cited by every `*-access` skill** (the
|
|
8
|
+
`leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent
|
|
9
|
+
per-skill prose). An access skill states its per-vendor mechanics — which token, which
|
|
10
|
+
CLI, which identity anchor — and cites this rule for the ordering. It never restates,
|
|
11
|
+
narrows, or locally overrides that ordering.
|
|
12
|
+
|
|
13
|
+
Settled by decision record `2026-08-12-credential-substrate-precedence` (D6), and
|
|
14
|
+
settled in the `settled-decisions` sense: re-arguing MCP-first inside a skill is out of
|
|
15
|
+
scope for that skill's work.
|
|
16
|
+
|
|
17
|
+
## The ladder
|
|
18
|
+
|
|
19
|
+
1. **Tier 1 — configured-provider substrate.** The token or CLI path fed by
|
|
20
|
+
`lisa-secrets-access`, chosen whenever its bootstrap credential is available **and**
|
|
21
|
+
the resolved substrate identity-matches the configured tenant/workspace/site.
|
|
22
|
+
`lisa-secrets-access` is the single chokepoint — never read an OS keychain a second
|
|
23
|
+
time.
|
|
24
|
+
2. **Tier 2 — interactive MCP**, used only when tier 1 is *genuinely* unavailable:
|
|
25
|
+
no bootstrap, no adapter for the operation (per-operation, not per-session), or a
|
|
26
|
+
provider outage. "The MCP happens to be authenticated" and "tier 1 is slower" are
|
|
27
|
+
**not** qualifying reasons.
|
|
28
|
+
3. **Tier 3 — loud, actionable failure** naming the exact credential to set and the exact
|
|
29
|
+
remediation. Never silently no-op, never blind-retry a failed or absent substrate,
|
|
30
|
+
never fall through to one that failed identity-match.
|
|
31
|
+
|
|
32
|
+
## Identity-match is mandatory on every substrate
|
|
33
|
+
|
|
34
|
+
Verified **in both directions** before any operation: the substrate must claim the
|
|
35
|
+
configured tenant, and the configured tenant must be one the substrate can reach. A
|
|
36
|
+
substrate authenticated as a different account is **skipped, never used — including at
|
|
37
|
+
tier 1**. A credential is not an identity claim; the identity claim is what the provider
|
|
38
|
+
says when asked. Skipping the check because "the user obviously meant this workspace" is
|
|
39
|
+
forbidden.
|
|
40
|
+
|
|
41
|
+
## Mutating operations: fallback is guarded, never routine
|
|
42
|
+
|
|
43
|
+
Falling back to an ambient-bound substrate for a **write** requires: switch profile and
|
|
44
|
+
assert identity immediately before the write → write → re-read the affected objects →
|
|
45
|
+
assert the tenant **from the response** (self URL host, cloudId in the path, response
|
|
46
|
+
metadata), not from the pre-flight check → on mismatch, stop, report a cross-tenant
|
|
47
|
+
hazard, and best-effort roll back. A successful pre-flight switch is not sufficient:
|
|
48
|
+
another process can mutate global state between the check and the write.
|
|
49
|
+
|
|
50
|
+
Full contract (per-vendor identity anchors and probes, the provider-first rationale, MCP's
|
|
51
|
+
first-class fallback role, consequences, and the checklist for adding or editing an access
|
|
52
|
+
skill): [reference/credential-substrate-precedence.md](../reference/credential-substrate-precedence.md).
|
|
@@ -48,7 +48,7 @@ platforms it requires and that each named platform has a configured runner.
|
|
|
48
48
|
"schemaVersion": 1,
|
|
49
49
|
"asOf": "<ISO date>",
|
|
50
50
|
"runnerPlatforms": { "<runner>": ["<platform>", "..."] },
|
|
51
|
-
"coverageFloor": { "<platform>": "<0-100,
|
|
51
|
+
"coverageFloor": { "<platform>": "<0-100, an absolute bar checked in enforced mode — not a ratchet, set once and left alone>" },
|
|
52
52
|
"platformWaivers": [
|
|
53
53
|
{
|
|
54
54
|
"scenario": "BDD-DOMAIN-NNN",
|
|
@@ -123,7 +123,9 @@ Two commands, wired into the project's script surface and into CI:
|
|
|
123
123
|
existing mapping);
|
|
124
124
|
- a discovered test named by no mapping and no exclusion, or an exclusion that no longer excuses
|
|
125
125
|
anything;
|
|
126
|
-
- a
|
|
126
|
+
- a platform sitting below its committed `coverageFloor`;
|
|
127
|
+
- coverage given back: an obligation mapped at the base revision that nothing maps here;
|
|
128
|
+
- new behavior nobody mapped or waived.
|
|
127
129
|
|
|
128
130
|
Regeneration is never blocked by the check: `--write` rewrites the report and burndown whenever a
|
|
129
131
|
report can be built at all, so a stale evidence string can never hold hostage the paperwork that
|
|
@@ -134,12 +136,20 @@ that currently fails is a red CI check, a separate signal; the map only asserts
|
|
|
134
136
|
exists and still says what it claimed. Both facts are required — a green gate over a red suite is
|
|
135
137
|
not coverage.
|
|
136
138
|
|
|
137
|
-
### Coverage floor, not coverage target
|
|
139
|
+
### Coverage floor, not coverage target — and not a ratchet
|
|
138
140
|
|
|
139
|
-
Projects adopting this contract mid-life start below 100% and must not be blocked by that. The
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
Projects adopting this contract mid-life start below 100% and must not be blocked by that. The
|
|
142
|
+
committed `coverageFloor` per platform is an **absolute bar** answering "is this platform below it
|
|
143
|
+
right now". Set it once at adoption to the honest measured number (or `0`) and leave it: nothing
|
|
144
|
+
forces it upward, and lowering it needs no ceremony.
|
|
145
|
+
|
|
146
|
+
What stops coverage sliding backwards is checked directly, per obligation, against the base
|
|
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 two artifacts one author cannot
|
|
149
|
+
produce alone: a recorded route (a `retirements` record or a `platformWaivers` entry) plus the
|
|
150
|
+
maintainer-applied `bdd-floor-baseline` label. Gaps that predate the change are burndown, never a
|
|
151
|
+
gate failure — which is what lets a brownfield project adopt `enforced` without first backfilling
|
|
152
|
+
its whole history.
|
|
143
153
|
|
|
144
154
|
## Waivers versus `@blocked`
|
|
145
155
|
|
|
@@ -198,7 +208,8 @@ A repo with no contract yet, taking its first frontend work item:
|
|
|
198
208
|
during this step, never left undisclosed.
|
|
199
209
|
3. **Write only this item's scenarios.** The first item is not a backfill project. Pre-existing
|
|
200
210
|
uncovered behavior becomes burndown in `docs/e2e-bdd-coverage.md`, and the floor starts where the
|
|
201
|
-
repo actually is.
|
|
211
|
+
repo actually is. That is a one-time act, not a recurring one: from here on the floor stays put
|
|
212
|
+
and what protects each new obligation is the per-obligation check, not the number.
|
|
202
213
|
4. **Seal this item's obligations** and commit the regenerated matrix and burndown with the change.
|
|
203
214
|
|
|
204
215
|
If a required platform has **no** e2e runner at all, that obligation is never left as a bare `N/A` —
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
* File families the ratchet watches. `kind` selects the extractor;
|
|
11
11
|
* `direction` applies to numeric-leaf kinds ("min" values may only rise,
|
|
12
12
|
* "max" values may only fall).
|
|
13
|
+
*
|
|
14
|
+
* PER-FAMILY POLICY, reviewed 2026-08-12. A family keeps its ratchet unless a
|
|
15
|
+
* NAMED deterministic non-regression invariant replaces the property the
|
|
16
|
+
* ratchet was providing — deleting a ratchet deletes that property with it, so
|
|
17
|
+
* "this generates churn" is a reason to find a replacement, never a reason to
|
|
18
|
+
* delete on its own:
|
|
19
|
+
*
|
|
20
|
+
* coverage / simplecov / e2e KEPT. Here the ratchet IS the non-regression
|
|
21
|
+
* invariant, and no per-item equivalent exists short of committing a
|
|
22
|
+
* per-file coverage baseline — an artifact that only ever accumulates.
|
|
23
|
+
* Revisit if one appears.
|
|
24
|
+
* stryker KEPT. `thresholds.break` is an absolute floor,
|
|
25
|
+
* kept outright; the mutate-list comparison detects EXEMPTION ADDITIONS
|
|
26
|
+
* rather than creep, and has no number for a pull request to nudge.
|
|
27
|
+
* eslint / rubocop / k6 / lisa-config KEPT, unchanged.
|
|
28
|
+
*
|
|
29
|
+
* Exactly one family was replaced, and it is not watched here and never was:
|
|
30
|
+
* the BDD traceability floor, whose numeric ratchet gave way to per-obligation
|
|
31
|
+
* checks. See `expo/copy-overwrite/scripts/bdd/baseline.mjs`.
|
|
32
|
+
*
|
|
33
|
+
* Retiring a family is SEQUENCED: the replacement invariant lands, then a
|
|
34
|
+
* `thresholdRatchet.allow` entry merges from the base side, then the mechanism
|
|
35
|
+
* changes. Never the reverse — this checker is precisely what stops a change
|
|
36
|
+
* granting itself the exception that permits it.
|
|
13
37
|
*/
|
|
14
38
|
export const FAMILIES = [
|
|
15
39
|
{
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
* File families the ratchet watches. `kind` selects the extractor;
|
|
11
11
|
* `direction` applies to numeric-leaf kinds ("min" values may only rise,
|
|
12
12
|
* "max" values may only fall).
|
|
13
|
+
*
|
|
14
|
+
* PER-FAMILY POLICY, reviewed 2026-08-12. A family keeps its ratchet unless a
|
|
15
|
+
* NAMED deterministic non-regression invariant replaces the property the
|
|
16
|
+
* ratchet was providing — deleting a ratchet deletes that property with it, so
|
|
17
|
+
* "this generates churn" is a reason to find a replacement, never a reason to
|
|
18
|
+
* delete on its own:
|
|
19
|
+
*
|
|
20
|
+
* coverage / simplecov / e2e KEPT. Here the ratchet IS the non-regression
|
|
21
|
+
* invariant, and no per-item equivalent exists short of committing a
|
|
22
|
+
* per-file coverage baseline — an artifact that only ever accumulates.
|
|
23
|
+
* Revisit if one appears.
|
|
24
|
+
* stryker KEPT. `thresholds.break` is an absolute floor,
|
|
25
|
+
* kept outright; the mutate-list comparison detects EXEMPTION ADDITIONS
|
|
26
|
+
* rather than creep, and has no number for a pull request to nudge.
|
|
27
|
+
* eslint / rubocop / k6 / lisa-config KEPT, unchanged.
|
|
28
|
+
*
|
|
29
|
+
* Exactly one family was replaced, and it is not watched here and never was:
|
|
30
|
+
* the BDD traceability floor, whose numeric ratchet gave way to per-obligation
|
|
31
|
+
* checks. See `expo/copy-overwrite/scripts/bdd/baseline.mjs`.
|
|
32
|
+
*
|
|
33
|
+
* Retiring a family is SEQUENCED: the replacement invariant lands, then a
|
|
34
|
+
* `thresholdRatchet.allow` entry merges from the base side, then the mechanism
|
|
35
|
+
* changes. Never the reverse — this checker is precisely what stops a change
|
|
36
|
+
* granting itself the exception that permits it.
|
|
13
37
|
*/
|
|
14
38
|
export const FAMILIES = [
|
|
15
39
|
{
|