@codyswann/lisa 3.46.4 → 3.47.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.
- package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +78 -2
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +1 -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 +10 -4
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +5 -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/lisa-enforcement-fallback.sh +78 -2
- package/typescript/copy-overwrite/.prettierignore +7 -1
- package/typescript/copy-overwrite/eslint.ignore.config.json +2 -0
package/package.json
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"test": "vitest run",
|
|
9
9
|
"test:unit": "vitest run --exclude='**/integration/**'",
|
|
10
10
|
"test:cov": "vitest run --coverage",
|
|
11
|
+
"pretest:mutation": "[ -d dist/configs ] || bun run build",
|
|
12
|
+
"test:mutation": "stryker run",
|
|
11
13
|
"lint": "oxlint --disable-nested-config && eslint . --quiet",
|
|
12
14
|
"lint:fix": "oxlint --fix --disable-nested-config && eslint . --fix",
|
|
13
15
|
"lint:slow": "eslint . --config eslint.slow.config.ts --quiet",
|
|
@@ -136,7 +138,7 @@
|
|
|
136
138
|
"zod-validation-error": "^4.0.0"
|
|
137
139
|
},
|
|
138
140
|
"name": "@codyswann/lisa",
|
|
139
|
-
"version": "3.
|
|
141
|
+
"version": "3.47.1",
|
|
140
142
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
141
143
|
"main": "dist/index.js",
|
|
142
144
|
"exports": {
|
|
@@ -264,6 +266,8 @@
|
|
|
264
266
|
"devDependencies": {
|
|
265
267
|
"@codyswann/lisa": "^2.328.0",
|
|
266
268
|
"@playwright/test": "^1.61.1",
|
|
269
|
+
"@stryker-mutator/core": "^9.0.0",
|
|
270
|
+
"@stryker-mutator/vitest-runner": "^9.0.0",
|
|
267
271
|
"@types/js-yaml": "^4.0.9",
|
|
268
272
|
"@types/semver": "^7.7.1",
|
|
269
273
|
"eslint-plugin-oxlint": "^1.62.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.47.1",
|
|
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.47.1",
|
|
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.47.1",
|
|
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.47.1",
|
|
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.47.1",
|
|
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"
|
|
@@ -22,7 +22,25 @@ set -uo pipefail
|
|
|
22
22
|
|
|
23
23
|
payload="$(cat)"
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
# `:-` substitutes on unset and on set-but-empty, and on nothing else. A value
|
|
26
|
+
# of " " is neither: `-n " "` is true, so it used to survive the emptiness test
|
|
27
|
+
# below, every candidate path became " /scripts/lisa-hooks/..." , no file
|
|
28
|
+
# matched, and every guard was skipped. That is the empty-string-fallback class
|
|
29
|
+
# verbatim — a value that passes the truthiness test, normalizes to nothing, and
|
|
30
|
+
# makes the downstream match find nothing.
|
|
31
|
+
#
|
|
32
|
+
# So the variable is trimmed FIRST and the substitution keyed off the trimmed
|
|
33
|
+
# value. Whitespace then reaches `git rev-parse` exactly as an unset variable
|
|
34
|
+
# does, instead of resolving to a root that cannot exist.
|
|
35
|
+
repo_root="${CLAUDE_PROJECT_DIR-}"
|
|
36
|
+
repo_root="${repo_root#"${repo_root%%[![:space:]]*}"}"
|
|
37
|
+
repo_root="${repo_root%"${repo_root##*[![:space:]]}"}"
|
|
38
|
+
if [ -z "$repo_root" ]; then
|
|
39
|
+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)"
|
|
40
|
+
fi
|
|
41
|
+
# No root at all means no repository to protect — a tool call outside any
|
|
42
|
+
# checkout. That is a genuine absence of subject matter, not a missing guard,
|
|
43
|
+
# and is the one case that still stands down.
|
|
26
44
|
[ -n "$repo_root" ] || exit 0
|
|
27
45
|
|
|
28
46
|
# There is deliberately no skip here, and that is the whole point.
|
|
@@ -66,6 +84,8 @@ repo_root="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null)}"
|
|
|
66
84
|
# host project whose plugin install fails has exactly the same hole and no
|
|
67
85
|
# `plugins/` directory to fall back on.
|
|
68
86
|
status=0
|
|
87
|
+
resolved=0
|
|
88
|
+
missing=""
|
|
69
89
|
for guard in block-no-verify parity-safety-net block-shell-json-parsing \
|
|
70
90
|
block-instruction-file-edits block-direct-issue-create \
|
|
71
91
|
block-managed-file-edits; do
|
|
@@ -78,7 +98,11 @@ for guard in block-no-verify parity-safety-net block-shell-json-parsing \
|
|
|
78
98
|
break
|
|
79
99
|
fi
|
|
80
100
|
done
|
|
81
|
-
[ -
|
|
101
|
+
if [ -z "$script" ]; then
|
|
102
|
+
missing="${missing:+$missing, }$guard"
|
|
103
|
+
continue
|
|
104
|
+
fi
|
|
105
|
+
resolved=$((resolved + 1))
|
|
82
106
|
# Each guard reads the tool payload on stdin and signals a refusal with exit
|
|
83
107
|
# 2. The payload is replayed to every one of them, and the strongest refusal
|
|
84
108
|
# is returned — a guard that declines must not be able to clear one that did
|
|
@@ -108,4 +132,56 @@ for guard in block-no-verify parity-safety-net block-shell-json-parsing \
|
|
|
108
132
|
fi
|
|
109
133
|
done
|
|
110
134
|
|
|
135
|
+
# Zero guards resolved is a refusal, not a pass.
|
|
136
|
+
#
|
|
137
|
+
# Six `continue`s used to leave `status` at 0, so nothing distinguished "every
|
|
138
|
+
# guard ran and none objected" from "no guard was found". That is the same
|
|
139
|
+
# silent fail-open this file was written to close, reproduced one layer down: a
|
|
140
|
+
# host whose `scripts/lisa-hooks/` was never written by `lisa apply`, or was
|
|
141
|
+
# deleted, or drifted — precisely the state this file exists for — got the same
|
|
142
|
+
# green as a clean session.
|
|
143
|
+
#
|
|
144
|
+
# Refusing rather than warning is a deliberate choice between two imperfect
|
|
145
|
+
# options, and the reasons are these.
|
|
146
|
+
#
|
|
147
|
+
# - The hook entry and the guards ship from the SAME `lisa apply`:
|
|
148
|
+
# `all/merge/.claude/settings.json` registers this dispatcher and
|
|
149
|
+
# `all/copy-overwrite/scripts/lisa-hooks/` writes the guards. "Registered
|
|
150
|
+
# but no guards" is therefore never a configuration anyone chose; it is
|
|
151
|
+
# always drift, deletion, or a partial apply.
|
|
152
|
+
# - Warning on exit 0 is barely louder than silence. Claude Code shows a
|
|
153
|
+
# zero-status hook's output to the user in transcript mode only and never
|
|
154
|
+
# to the agent, so "fail loud, exit unchanged" would have left the failure
|
|
155
|
+
# very nearly as invisible as it already was while claiming to have fixed
|
|
156
|
+
# it.
|
|
157
|
+
# - The blocking cost is bounded and recoverable without the agent. The
|
|
158
|
+
# refusal below names the guards, both searched paths, and the one command
|
|
159
|
+
# that repairs it, which a human runs in a terminal — no tool call needed.
|
|
160
|
+
#
|
|
161
|
+
# The scope is deliberately "zero", not "fewer than six". A partial resolution
|
|
162
|
+
# means some enforcement ran, and version skew across an interrupted apply is a
|
|
163
|
+
# real enough way to reach it that refusing there would trade a silent hole for
|
|
164
|
+
# a noisy outage.
|
|
165
|
+
if [ "$resolved" -eq 0 ]; then
|
|
166
|
+
cat >&2 <<EOF
|
|
167
|
+
Blocked: Lisa's enforcement guards are missing from this repository, so this
|
|
168
|
+
tool call was checked by nothing at all.
|
|
169
|
+
|
|
170
|
+
This hook is registered in .claude/settings.json but resolved none of the
|
|
171
|
+
guards it dispatches: $missing
|
|
172
|
+
|
|
173
|
+
Searched:
|
|
174
|
+
$repo_root/scripts/lisa-hooks/<guard>.sh
|
|
175
|
+
$repo_root/plugins/lisa/hooks/<guard>.sh
|
|
176
|
+
|
|
177
|
+
Refused rather than allowed on purpose. A dispatcher that resolves nothing is
|
|
178
|
+
indistinguishable from one that was never installed, and letting the call
|
|
179
|
+
through would be the silent fail-open this hook exists to close.
|
|
180
|
+
|
|
181
|
+
To repair, run this in a terminal outside the agent session:
|
|
182
|
+
npx @codyswann/lisa apply
|
|
183
|
+
EOF
|
|
184
|
+
exit 2
|
|
185
|
+
fi
|
|
186
|
+
|
|
111
187
|
exit "$status"
|
|
@@ -85,4 +85,10 @@ scripts/lisa-schema-validate.mjs
|
|
|
85
85
|
scripts/lisa-test-node.mjs
|
|
86
86
|
scripts/lisa-work-item.mjs
|
|
87
87
|
scripts/threshold-ratchet-compare.mjs
|
|
88
|
-
scripts/threshold-ratchet-families.mjs
|
|
88
|
+
scripts/threshold-ratchet-families.mjs
|
|
89
|
+
|
|
90
|
+
# Mutation gate sandbox: a full second copy of the tree written by
|
|
91
|
+
# `test:mutation`. Formatting or linting it reports every source file twice, and
|
|
92
|
+
# the copy is outside every tsconfig project so the second report is a parse
|
|
93
|
+
# error -- 1191 of them, measured, from one leftover sandbox.
|
|
94
|
+
.stryker-tmp
|