@codyswann/lisa 2.342.0 → 2.342.2

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 (69) hide show
  1. package/all/copy-overwrite/scripts/lisa-floor-collisions.mjs +38 -6
  2. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +44 -13
  3. package/all/create-only/scripts/remote-agent-aws-setup.sh +8 -1
  4. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.js +8 -7
  6. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  7. package/dist/opencode/plugin-templates/parity-safety-net.sh +44 -13
  8. package/package.json +1 -1
  9. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa/hooks/parity-safety-net.sh +44 -13
  12. package/plugins/lisa/hooks/threshold-ratchet.mjs +39 -5
  13. package/plugins/lisa-agy/hooks/parity-safety-net.sh +44 -13
  14. package/plugins/lisa-agy/plugin.json +1 -1
  15. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  18. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +44 -13
  22. package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +39 -5
  23. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +44 -13
  25. package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +39 -5
  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/hooks/parity-safety-net.sh +44 -13
  67. package/plugins/src/base/hooks/threshold-ratchet.mjs +39 -5
  68. package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +39 -5
  69. package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +39 -5
@@ -56,6 +56,15 @@ const GIT = GIT_LOCATIONS.find(candidate => fs.existsSync(candidate)) ?? "git";
56
56
 
57
57
  /** Git flag shared by every changed-file listing. */
58
58
  const NAME_ONLY = "--name-only";
59
+ /**
60
+ * Suppress rename detection when discovering changed files.
61
+ *
62
+ * With it on, `git diff --name-only` reports a rename as the destination path
63
+ * only. Moving a watched threshold file to an unwatched path therefore lists
64
+ * one name the ratchet does not watch, and the loosening at the old path is
65
+ * never compared. Both sides have to be visible for the gate to mean anything.
66
+ */
67
+ const NO_RENAMES = "--no-renames";
59
68
 
60
69
  /**
61
70
  * Run git, returning stdout or null on any failure.
@@ -87,7 +96,7 @@ function git(args, cwd) {
87
96
  */
88
97
  function resolvePlan(mode, root, baseRef, onlyFiles) {
89
98
  if (mode === "staged") {
90
- const diff = git(["diff", "--cached", NAME_ONLY], root);
99
+ const diff = git(["diff", "--cached", NAME_ONLY, NO_RENAMES], root);
91
100
  if (diff === null) return null;
92
101
  return {
93
102
  files: diff.split("\n").filter(Boolean),
@@ -99,7 +108,7 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
99
108
  if (!baseRef) return null;
100
109
  const mergeBase = git(["merge-base", baseRef, "HEAD"], root)?.trim();
101
110
  if (!mergeBase) return null;
102
- const diff = git(["diff", NAME_ONLY, mergeBase, "HEAD"], root);
111
+ const diff = git(["diff", NAME_ONLY, NO_RENAMES, mergeBase, "HEAD"], root);
103
112
  if (diff === null) return null;
104
113
  return {
105
114
  files: diff.split("\n").filter(Boolean),
@@ -107,7 +116,7 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
107
116
  readCurrent: f => git(["show", `HEAD:${f}`], root),
108
117
  };
109
118
  }
110
- const diff = git(["diff", NAME_ONLY, "HEAD"], root);
119
+ const diff = git(["diff", NAME_ONLY, NO_RENAMES, "HEAD"], root);
111
120
  if (diff === null) return null;
112
121
  return {
113
122
  files: onlyFiles ?? diff.split("\n").filter(Boolean),
@@ -122,6 +131,31 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
122
131
  };
123
132
  }
124
133
 
134
+ /**
135
+ * Decide the exit code when the ratchet cannot determine what changed.
136
+ *
137
+ * `staged` and `base` are enforcement gates — pre-commit and CI. A gate that
138
+ * cannot see the change set has not found the change set clean, and returning 0
139
+ * reports exactly that. It fails closed, loudly.
140
+ *
141
+ * `hook` is advisory feedback to an agent mid-edit, fires on every tool call,
142
+ * and blocks nothing downstream. Failing it closed on a transient git hiccup
143
+ * would turn a hint into an outage, so it stays permissive — but still says so.
144
+ * @param {"hook"|"staged"|"base"} mode Comparison mode
145
+ * @param {string} reason What could not be determined
146
+ * @returns {number} Process exit code
147
+ */
148
+ function undeterminable(mode, reason) {
149
+ process.stderr.write(
150
+ `threshold-ratchet: ${reason}; the ratchet could not run in ${mode} mode\n`
151
+ );
152
+ if (mode === "hook") return 0;
153
+ process.stderr.write(
154
+ "threshold-ratchet: failing closed — an enforcement gate that cannot read the change set has not verified it\n"
155
+ );
156
+ return 1;
157
+ }
158
+
125
159
  /**
126
160
  * Run the ratchet for a mode, print the report, and return the exit code.
127
161
  * @param {"hook"|"staged"|"base"} mode Comparison mode
@@ -131,9 +165,9 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
131
165
  */
132
166
  function run(mode, baseRef, onlyFiles) {
133
167
  const root = git(["rev-parse", "--show-toplevel"])?.trim();
134
- if (!root) return 0;
168
+ if (!root) return undeterminable(mode, "not a git repository");
135
169
  const plan = resolvePlan(mode, root, baseRef, onlyFiles);
136
- if (!plan) return 0;
170
+ if (!plan) return undeterminable(mode, "could not resolve the changed files");
137
171
 
138
172
  const watched = plan.files.filter(f => familyFor(f));
139
173
  if (watched.length === 0) return 0;
@@ -56,6 +56,15 @@ const GIT = GIT_LOCATIONS.find(candidate => fs.existsSync(candidate)) ?? "git";
56
56
 
57
57
  /** Git flag shared by every changed-file listing. */
58
58
  const NAME_ONLY = "--name-only";
59
+ /**
60
+ * Suppress rename detection when discovering changed files.
61
+ *
62
+ * With it on, `git diff --name-only` reports a rename as the destination path
63
+ * only. Moving a watched threshold file to an unwatched path therefore lists
64
+ * one name the ratchet does not watch, and the loosening at the old path is
65
+ * never compared. Both sides have to be visible for the gate to mean anything.
66
+ */
67
+ const NO_RENAMES = "--no-renames";
59
68
 
60
69
  /**
61
70
  * Run git, returning stdout or null on any failure.
@@ -87,7 +96,7 @@ function git(args, cwd) {
87
96
  */
88
97
  function resolvePlan(mode, root, baseRef, onlyFiles) {
89
98
  if (mode === "staged") {
90
- const diff = git(["diff", "--cached", NAME_ONLY], root);
99
+ const diff = git(["diff", "--cached", NAME_ONLY, NO_RENAMES], root);
91
100
  if (diff === null) return null;
92
101
  return {
93
102
  files: diff.split("\n").filter(Boolean),
@@ -99,7 +108,7 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
99
108
  if (!baseRef) return null;
100
109
  const mergeBase = git(["merge-base", baseRef, "HEAD"], root)?.trim();
101
110
  if (!mergeBase) return null;
102
- const diff = git(["diff", NAME_ONLY, mergeBase, "HEAD"], root);
111
+ const diff = git(["diff", NAME_ONLY, NO_RENAMES, mergeBase, "HEAD"], root);
103
112
  if (diff === null) return null;
104
113
  return {
105
114
  files: diff.split("\n").filter(Boolean),
@@ -107,7 +116,7 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
107
116
  readCurrent: f => git(["show", `HEAD:${f}`], root),
108
117
  };
109
118
  }
110
- const diff = git(["diff", NAME_ONLY, "HEAD"], root);
119
+ const diff = git(["diff", NAME_ONLY, NO_RENAMES, "HEAD"], root);
111
120
  if (diff === null) return null;
112
121
  return {
113
122
  files: onlyFiles ?? diff.split("\n").filter(Boolean),
@@ -122,6 +131,31 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
122
131
  };
123
132
  }
124
133
 
134
+ /**
135
+ * Decide the exit code when the ratchet cannot determine what changed.
136
+ *
137
+ * `staged` and `base` are enforcement gates — pre-commit and CI. A gate that
138
+ * cannot see the change set has not found the change set clean, and returning 0
139
+ * reports exactly that. It fails closed, loudly.
140
+ *
141
+ * `hook` is advisory feedback to an agent mid-edit, fires on every tool call,
142
+ * and blocks nothing downstream. Failing it closed on a transient git hiccup
143
+ * would turn a hint into an outage, so it stays permissive — but still says so.
144
+ * @param {"hook"|"staged"|"base"} mode Comparison mode
145
+ * @param {string} reason What could not be determined
146
+ * @returns {number} Process exit code
147
+ */
148
+ function undeterminable(mode, reason) {
149
+ process.stderr.write(
150
+ `threshold-ratchet: ${reason}; the ratchet could not run in ${mode} mode\n`
151
+ );
152
+ if (mode === "hook") return 0;
153
+ process.stderr.write(
154
+ "threshold-ratchet: failing closed — an enforcement gate that cannot read the change set has not verified it\n"
155
+ );
156
+ return 1;
157
+ }
158
+
125
159
  /**
126
160
  * Run the ratchet for a mode, print the report, and return the exit code.
127
161
  * @param {"hook"|"staged"|"base"} mode Comparison mode
@@ -131,9 +165,9 @@ function resolvePlan(mode, root, baseRef, onlyFiles) {
131
165
  */
132
166
  function run(mode, baseRef, onlyFiles) {
133
167
  const root = git(["rev-parse", "--show-toplevel"])?.trim();
134
- if (!root) return 0;
168
+ if (!root) return undeterminable(mode, "not a git repository");
135
169
  const plan = resolvePlan(mode, root, baseRef, onlyFiles);
136
- if (!plan) return 0;
170
+ if (!plan) return undeterminable(mode, "could not resolve the changed files");
137
171
 
138
172
  const watched = plan.files.filter(f => familyFor(f));
139
173
  if (watched.length === 0) return 0;