@codyswann/lisa 2.241.0 → 2.242.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.
Files changed (80) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +10 -1
  3. package/plugins/lisa/.codex-plugin/hooks.json +9 -0
  4. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  5. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +315 -0
  6. package/plugins/lisa/hooks/threshold-ratchet-families.mjs +295 -0
  7. package/plugins/lisa/hooks/threshold-ratchet.mjs +213 -0
  8. package/plugins/lisa/hooks/threshold-ratchet.sh +22 -0
  9. package/plugins/lisa-agy/plugin.json +1 -1
  10. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  13. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-copilot/.claude-plugin/plugin.json +10 -1
  16. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +315 -0
  17. package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +295 -0
  18. package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +213 -0
  19. package/plugins/lisa-copilot/hooks/threshold-ratchet.sh +22 -0
  20. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cursor/hooks/hooks.json +4 -0
  22. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +315 -0
  23. package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +295 -0
  24. package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +213 -0
  25. package/plugins/lisa-cursor/hooks/threshold-ratchet.sh +22 -0
  26. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-agy/plugin.json +1 -1
  29. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  49. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-agy/plugin.json +1 -1
  54. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  59. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  64. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/src/base/.claude-plugin/plugin.json +9 -0
  67. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +315 -0
  68. package/plugins/src/base/hooks/threshold-ratchet-families.mjs +295 -0
  69. package/plugins/src/base/hooks/threshold-ratchet.mjs +213 -0
  70. package/plugins/src/base/hooks/threshold-ratchet.sh +22 -0
  71. package/rails/copy-overwrite/lefthook.yml +6 -0
  72. package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +213 -0
  73. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +315 -0
  74. package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +295 -0
  75. package/scripts/build-plugins.sh +20 -0
  76. package/scripts/lib/per-agent-hook-filter.mjs +7 -0
  77. package/typescript/copy-contents/.husky/pre-commit +17 -0
  78. package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +213 -0
  79. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +315 -0
  80. package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +295 -0
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Threshold ratchet gate — quality thresholds may tighten, never weaken.
4
+ *
5
+ * Deterministic comparator shared by three enforcement layers:
6
+ * 1. Agent-time soft block: PostToolUse hook via threshold-ratchet.sh
7
+ * (`--hook`, exit 2 on weakening so the agent gets actionable feedback).
8
+ * 2. Pre-commit backstop: husky / lefthook (`--staged`, exit 1).
9
+ * 3. CI gate: reusable quality workflows (`--base <ref>`, exit 1),
10
+ * comparing against the merge-base so nothing weakened lands in a PR.
11
+ *
12
+ * Tier 1 — designed tunables: vitest/jest/simplecov/e2e thresholds
13
+ * (minimums) and eslint/rubocop thresholds (maximums). Tier 2 — stryker's
14
+ * break score and k6 expression bounds. Tier 3 — exemption additions
15
+ * (audit-ignore entries, stryker mutate exclusions, thresholdRatchet.allow
16
+ * entries) which weaken a gate without touching a number.
17
+ *
18
+ * Human override: `.lisa.config.json` → `thresholdRatchet.allow` entries
19
+ * ({ file, key, reason }). Honored ONLY from the baseline side (HEAD /
20
+ * merge-base), never from the change under review — an agent cannot grant
21
+ * itself an exception in the same change that weakens a gate. `key: "*"`
22
+ * allows every key in the file.
23
+ *
24
+ * Extraction lives in threshold-ratchet-families.mjs; comparison rules in
25
+ * threshold-ratchet-compare.mjs. Zero dependencies.
26
+ */
27
+ import { execFileSync } from "node:child_process";
28
+ import * as fs from "node:fs";
29
+ import * as path from "node:path";
30
+ import { fileURLToPath } from "node:url";
31
+ import {
32
+ extractAllowEntries,
33
+ familyFor,
34
+ parseJson,
35
+ } from "./threshold-ratchet-families.mjs";
36
+ import {
37
+ applyAllowList,
38
+ compareFile,
39
+ formatReport,
40
+ } from "./threshold-ratchet-compare.mjs";
41
+
42
+ /**
43
+ * Standard git locations, checked in order so the executable comes from a
44
+ * fixed, unwriteable directory rather than a PATH lookup. The bare "git"
45
+ * fallback keeps unusual layouts (e.g. Windows git-bash) working.
46
+ */
47
+ const GIT_LOCATIONS = [
48
+ "/usr/bin/git",
49
+ "/usr/local/bin/git",
50
+ "/opt/homebrew/bin/git",
51
+ ];
52
+ const GIT = GIT_LOCATIONS.find(candidate => fs.existsSync(candidate)) ?? "git";
53
+
54
+ /** Git flag shared by every changed-file listing. */
55
+ const NAME_ONLY = "--name-only";
56
+
57
+ /**
58
+ * Run git, returning stdout or null on any failure.
59
+ * @param {string[]} args Git arguments
60
+ * @param {string} [cwd] Working directory
61
+ * @returns {string | null} Captured stdout, or null when git failed
62
+ */
63
+ function git(args, cwd) {
64
+ try {
65
+ return execFileSync(GIT, args, {
66
+ cwd,
67
+ encoding: "utf-8",
68
+ stdio: ["ignore", "pipe", "ignore"],
69
+ });
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Resolve mode-specific candidate files and content readers.
77
+ * @param {"hook"|"staged"|"base"} mode Comparison mode
78
+ * @param {string} root Repo root
79
+ * @param {string | undefined} baseRef Base ref (base mode only)
80
+ * @param {string[] | undefined} onlyFiles Restrict to these repo-relative
81
+ * paths (hook mode with a known edited file)
82
+ * @returns {{ files: string[], baselineRef: string, readCurrent: (f: string) => string | null } | null}
83
+ * The comparison plan, or null when git state can't support the mode
84
+ */
85
+ function resolvePlan(mode, root, baseRef, onlyFiles) {
86
+ if (mode === "staged") {
87
+ const diff = git(["diff", "--cached", NAME_ONLY], root);
88
+ if (diff === null) return null;
89
+ return {
90
+ files: diff.split("\n").filter(Boolean),
91
+ baselineRef: "HEAD",
92
+ readCurrent: f => git(["show", `:${f}`], root),
93
+ };
94
+ }
95
+ if (mode === "base") {
96
+ if (!baseRef) return null;
97
+ const mergeBase = git(["merge-base", baseRef, "HEAD"], root)?.trim();
98
+ if (!mergeBase) return null;
99
+ const diff = git(["diff", NAME_ONLY, mergeBase, "HEAD"], root);
100
+ if (diff === null) return null;
101
+ return {
102
+ files: diff.split("\n").filter(Boolean),
103
+ baselineRef: mergeBase,
104
+ readCurrent: f => git(["show", `HEAD:${f}`], root),
105
+ };
106
+ }
107
+ const diff = git(["diff", NAME_ONLY, "HEAD"], root);
108
+ if (diff === null) return null;
109
+ return {
110
+ files: onlyFiles ?? diff.split("\n").filter(Boolean),
111
+ baselineRef: "HEAD",
112
+ readCurrent: f => {
113
+ try {
114
+ return fs.readFileSync(path.join(root, f), "utf-8");
115
+ } catch {
116
+ return null;
117
+ }
118
+ },
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Run the ratchet for a mode, print the report, and return the exit code.
124
+ * @param {"hook"|"staged"|"base"} mode Comparison mode
125
+ * @param {string | undefined} [baseRef] Base ref (base mode only)
126
+ * @param {string[] | undefined} [onlyFiles] Restrict to these paths (hook mode)
127
+ * @returns {number} Process exit code (2 for hook mode, 1 otherwise; 0 clean)
128
+ */
129
+ function run(mode, baseRef, onlyFiles) {
130
+ const root = git(["rev-parse", "--show-toplevel"])?.trim();
131
+ if (!root) return 0;
132
+ const plan = resolvePlan(mode, root, baseRef, onlyFiles);
133
+ if (!plan) return 0;
134
+
135
+ const watched = plan.files.filter(f => familyFor(f));
136
+ if (watched.length === 0) return 0;
137
+
138
+ const findings = watched.flatMap(f =>
139
+ compareFile(
140
+ f,
141
+ git(["show", `${plan.baselineRef}:${f}`], root),
142
+ plan.readCurrent(f)
143
+ )
144
+ );
145
+ if (findings.length === 0) return 0;
146
+
147
+ const baselineConfig = parseJson(
148
+ git(["show", `${plan.baselineRef}:.lisa.config.json`], root)
149
+ );
150
+ const { blocked, allowed } = applyAllowList(
151
+ findings,
152
+ extractAllowEntries(baselineConfig)
153
+ );
154
+ for (const finding of allowed) {
155
+ process.stdout.write(
156
+ `threshold-ratchet: allowed by .lisa.config.json exception — ${finding.message}\n`
157
+ );
158
+ }
159
+ if (blocked.length === 0) return 0;
160
+ process.stderr.write(`${formatReport(blocked)}\n`);
161
+ return mode === "hook" ? 2 : 1;
162
+ }
163
+
164
+ /**
165
+ * Handle `--hook` mode: parse the tool-use event from stdin and scope the
166
+ * check to the edited file (Edit/Write/NotebookEdit) or every changed
167
+ * watched file (Bash).
168
+ * @returns {number} Process exit code
169
+ */
170
+ function runHookMode() {
171
+ const state = { stdin: "" };
172
+ try {
173
+ state.stdin = fs.readFileSync(0, "utf-8");
174
+ } catch {
175
+ return 0;
176
+ }
177
+ const input = parseJson(state.stdin);
178
+ if (!input || typeof input !== "object") return 0;
179
+ if (input.tool_name === "Bash") return run("hook");
180
+ if (!["Edit", "Write", "NotebookEdit"].includes(input.tool_name)) return 0;
181
+ const filePath = input.tool_input?.file_path;
182
+ if (typeof filePath !== "string") return 0;
183
+ const root = git(["rev-parse", "--show-toplevel"])?.trim();
184
+ if (!root) return 0;
185
+ const rel = path
186
+ .relative(root, path.resolve(filePath))
187
+ .split(path.sep)
188
+ .join("/");
189
+ if (rel.startsWith("..") || !familyFor(rel)) return 0;
190
+ return run("hook", undefined, [rel]);
191
+ }
192
+
193
+ /**
194
+ * CLI entrypoint.
195
+ * @returns {number} Process exit code
196
+ */
197
+ function main() {
198
+ const args = process.argv.slice(2);
199
+ if (args[0] === "--staged") return run("staged");
200
+ if (args[0] === "--base") return run("base", args[1]);
201
+ if (args[0] === "--hook") return runHookMode();
202
+ process.stderr.write(
203
+ "usage: threshold-ratchet.mjs --hook | --staged | --base <ref>\n"
204
+ );
205
+ return 0;
206
+ }
207
+
208
+ const isDirectRun =
209
+ process.argv[1] &&
210
+ fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
211
+ if (isDirectRun) {
212
+ process.exit(main());
213
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ # PostToolUse hook for Edit|Write|NotebookEdit|Bash: the threshold ratchet.
3
+ # Quality thresholds (coverage minimums, complexity maximums, mutation break
4
+ # score, e2e route floors, k6 bounds, audit-ignore lists) may tighten but never
5
+ # weaken. The deterministic comparator lives in threshold-ratchet.mjs and is
6
+ # shared with the pre-commit (husky/lefthook --staged) and CI (--base) layers,
7
+ # so this hook is fast feedback — not the only line of defense.
8
+ #
9
+ # Exit 2 on weakening (soft block: the agent gets the report on stderr and can
10
+ # fix the code or escalate to a human). Every infrastructure gap — no node, no
11
+ # git repo, unreadable stdin — exits 0: the CI layer still guarantees the gate,
12
+ # and a broken hook must never wedge an agent session.
13
+ set -euo pipefail
14
+
15
+ input="$(cat)"
16
+
17
+ command -v node >/dev/null 2>&1 || exit 0
18
+ git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
19
+
20
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+
22
+ printf '%s' "$input" | node "$script_dir/threshold-ratchet.mjs" --hook
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.241.0",
3
+ "version": "2.242.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": "2.241.0",
3
+ "version": "2.242.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": "2.241.0",
3
+ "version": "2.242.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": "2.241.0",
3
+ "version": "2.242.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": "2.241.0",
3
+ "version": "2.242.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-phaser",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.241.0",
3
+ "version": "2.242.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -63,6 +63,15 @@
63
63
  }
64
64
  ]
65
65
  },
66
+ {
67
+ "matcher": "Edit|Write|NotebookEdit|Bash",
68
+ "hooks": [
69
+ {
70
+ "type": "command",
71
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/threshold-ratchet.sh"
72
+ }
73
+ ]
74
+ },
66
75
  {
67
76
  "matcher": "TeamCreate|Agent",
68
77
  "hooks": [