@codyswann/lisa 4.4.9 → 4.4.11

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 (67) hide show
  1. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +78 -1
  2. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  3. package/dist/core/lisa-owned-hash-ledger.js +1 -0
  4. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  6. package/dist/core/upstream-evidence-manifest.js +6 -4
  7. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  8. package/dist/opencode/plugin-templates/parity-safety-net.sh +78 -1
  9. package/package.json +1 -1
  10. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa/hooks/parity-safety-net.sh +78 -1
  13. package/plugins/lisa-agy/hooks/parity-safety-net.sh +78 -1
  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 +78 -1
  22. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +78 -1
  24. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-agy/plugin.json +1 -1
  27. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  37. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  42. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  47. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-agy/plugin.json +1 -1
  52. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  57. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  62. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/materialized-artifacts.json +22 -0
  65. package/plugins/src/base/hooks/parity-safety-net.sh +78 -1
  66. package/scripts/build-plugins.sh +45 -1
  67. package/scripts/check-plugins-sync.sh +166 -2
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env bash
2
- # Fails if the generated plugin directories (plugins/lisa, plugins/lisa-*) are
3
- # out of sync with their source (plugins/src). This guards against editing the
2
+ # Fails if anything `build-plugins.sh` generates is out of sync with its source.
3
+ #
4
+ # That is two sets, and for a long time only the first was checked (#3064): the
5
+ # generated plugin directories under plugins/, and the files the same build
6
+ # materializes into the stack lanes and host guard directories WELL OUTSIDE
7
+ # plugins/. Both halves are checked here now, by the same mechanism.
8
+ #
9
+ # The plugins/ half. This guards against editing the
4
10
  # build artifact directly: build-plugins.sh runs `rm -rf plugins/lisa && cp -r
5
11
  # plugins/src/base`, so any artifact-only edit is silently discarded on the next
6
12
  # build/release. Two real PRs (#471, #478) were wiped this way before this check
@@ -22,8 +28,87 @@ if [ -n "$(git status --porcelain -- plugins/ 2>/dev/null)" ]; then
22
28
  exit 1
23
29
  fi
24
30
 
31
+ # The same precaution for the generated files OUTSIDE plugins/, using the
32
+ # committed manifest — which the check above has just proved is the committed
33
+ # one, since it lives under plugins/.
34
+ #
35
+ # Without this, a directly-edited copy that was never committed is REVERTED by
36
+ # the rebuild below and the tree reads clean: the check would pass having
37
+ # silently discarded the edit, which is the precise failure the plugins/
38
+ # pre-check exists to prevent. Absent on a first run, before any manifest has
39
+ # been committed; the post-build check covers that case.
40
+ MATERIALIZED_MANIFEST="$ROOT_DIR/plugins/materialized-artifacts.json"
41
+ committed_manifest_paths=""
42
+ if [ -f "$MATERIALIZED_MANIFEST" ]; then
43
+ committed_manifest_paths="$(jq -r '.[]' "$MATERIALIZED_MANIFEST" | LC_ALL=C sort)"
44
+ committed_generated=()
45
+ while IFS= read -r committed_path; do
46
+ if [ -n "$committed_path" ]; then
47
+ committed_generated+=("$committed_path")
48
+ fi
49
+ done < <(jq -r '.[]' "$MATERIALIZED_MANIFEST")
50
+ if [ "${#committed_generated[@]}" -gt 0 ]; then
51
+ pre_build_status="$(git status --porcelain -- "${committed_generated[@]}")"
52
+ if [ -n "$pre_build_status" ]; then
53
+ echo "✗ Generated files outside plugins/ have uncommitted changes before the sync check could run." >&2
54
+ echo "" >&2
55
+ printf "%s\n" "$pre_build_status" | sed 's/^/ /' >&2
56
+ echo "" >&2
57
+ echo " These are generated by 'bun run build:plugins'. Rebuilding would" >&2
58
+ echo " overwrite them, so the check refuses rather than discarding an edit" >&2
59
+ echo " and reporting a clean tree. Edit the canonical source instead, or" >&2
60
+ echo " stash, then re-run: bun run check:plugins" >&2
61
+ exit 1
62
+ fi
63
+ fi
64
+ fi
65
+
25
66
  bun run build:plugins >/dev/null
26
67
 
68
+ # Did the SET of destinations change? Asked before the plugins/ diff below,
69
+ # because the manifest lives under plugins/ and that diff would otherwise
70
+ # swallow this as a one-line "plugin artifacts out of sync" naming the manifest
71
+ # and nothing else — technically a refusal, but it tells you nothing about
72
+ # which destination appeared or vanished.
73
+ #
74
+ # This is the arm that makes an unexpectedly SMALL set fail. Every materialize
75
+ # call is guarded on its source and its generator being present, so a moved
76
+ # source does not error — it silently stops writing, and the copies it used to
77
+ # own become unowned files nothing checks. Comparing against the committed set
78
+ # names them.
79
+ if [ ! -f "$MATERIALIZED_MANIFEST" ]; then
80
+ echo "✗ $MATERIALIZED_MANIFEST is missing after the build." >&2
81
+ echo " build-plugins.sh writes it on every successful run, so its absence" >&2
82
+ echo " means the build did not complete — not that there is nothing to check." >&2
83
+ exit 1
84
+ fi
85
+ current_manifest_paths="$(jq -r '.[]' "$MATERIALIZED_MANIFEST" | LC_ALL=C sort)"
86
+ if [ "$current_manifest_paths" != "$committed_manifest_paths" ]; then
87
+ echo "✗ The set of files this build generates outside plugins/ has changed." >&2
88
+ echo "" >&2
89
+ added="$(comm -13 <(printf "%s\n" "$committed_manifest_paths") <(printf "%s\n" "$current_manifest_paths"))"
90
+ removed="$(comm -23 <(printf "%s\n" "$committed_manifest_paths") <(printf "%s\n" "$current_manifest_paths"))"
91
+ if [ -n "$added" ]; then
92
+ echo " Now generated, and not recorded before:" >&2
93
+ printf "%s\n" "$added" | sed 's/^/ /' >&2
94
+ echo "" >&2
95
+ fi
96
+ if [ -n "$removed" ]; then
97
+ echo " Recorded before, and NO LONGER generated:" >&2
98
+ printf "%s\n" "$removed" | sed 's/^/ /' >&2
99
+ echo "" >&2
100
+ echo " A destination that stops being generated is the dangerous half: the" >&2
101
+ echo " file stays in the tree, still shipped, and nothing regenerates or" >&2
102
+ echo " checks it. Confirm the materialize call was removed deliberately —" >&2
103
+ echo " and if it was, delete the copies it used to own." >&2
104
+ echo "" >&2
105
+ fi
106
+ echo " plugins/materialized-artifacts.json is written by 'bun run" >&2
107
+ echo " build:plugins' and records what that run actually wrote. Commit it" >&2
108
+ echo " together with the destinations above." >&2
109
+ exit 1
110
+ fi
111
+
27
112
  plugin_status="$(git status --porcelain -- plugins/)"
28
113
  if [ -n "$plugin_status" ]; then
29
114
  echo "✗ Generated plugin artifacts are out of sync with plugins/src." >&2
@@ -45,6 +130,85 @@ fi
45
130
 
46
131
  echo "✓ Plugin artifacts are in sync with plugins/src."
47
132
 
133
+ # The same build writes well OUTSIDE plugins/ — the shared ESM entry guard and
134
+ # child-start deadline into three stack lanes, the threshold-ratchet trio into
135
+ # two, the host enforcement guards, the Sonar wrapper, and the fallback
136
+ # dispatcher. Until #3064 none of them was reproducibility-checked, so a
137
+ # maintainer who edited a generated copy directly, or edited a canonical and
138
+ # forgot to rebuild, got no signal from the check whose name says it covers what
139
+ # the plugin build produces.
140
+ #
141
+ # The path set is DERIVED, never listed: build-plugins.sh records each
142
+ # destination it actually writes into plugins/materialized-artifacts.json, so a
143
+ # materialize call added tomorrow is covered without touching this file. A
144
+ # second hand-maintained list is exactly what let these drift, and would rot the
145
+ # same way.
146
+ #
147
+ # By here the manifest exists and matches the committed one — the set-change
148
+ # check above proved both. What is left is the contents of each destination.
149
+ generated_files=()
150
+ while IFS= read -r generated_path; do
151
+ if [ -n "$generated_path" ]; then
152
+ generated_files+=("$generated_path")
153
+ fi
154
+ done < <(jq -r '.[]' "$MATERIALIZED_MANIFEST")
155
+
156
+ # An empty inspection and a clean tree are otherwise indistinguishable: both
157
+ # print a tick. Refuse the empty one.
158
+ if [ "${#generated_files[@]}" -eq 0 ]; then
159
+ echo "✗ The build recorded ZERO generated files outside plugins/." >&2
160
+ echo "" >&2
161
+ echo " This check cannot pass by inspecting nothing. Every materialize call" >&2
162
+ echo " in build-plugins.sh is guarded on its source and its generator being" >&2
163
+ echo " present, so a missing scripts/materialize-copy-overwrite.mjs or a" >&2
164
+ echo " moved source silently skips the whole set." >&2
165
+ echo "" >&2
166
+ echo " Fix: run 'bun run build:plugins' and confirm" >&2
167
+ echo " plugins/materialized-artifacts.json lists the destinations again." >&2
168
+ exit 1
169
+ fi
170
+
171
+ # A destination git does not track can never be compared, so an untracked or
172
+ # gitignored one would be permanently invisible to the diff below — a green
173
+ # check over a file nobody is checking.
174
+ untracked_generated="$(
175
+ comm -23 \
176
+ <(printf "%s\n" "${generated_files[@]}" | LC_ALL=C sort) \
177
+ <(git ls-files -- "${generated_files[@]}" | LC_ALL=C sort)
178
+ )"
179
+ if [ -n "$untracked_generated" ]; then
180
+ echo "✗ Generated files outside plugins/ are not tracked by git." >&2
181
+ echo "" >&2
182
+ printf "%s\n" "$untracked_generated" | sed 's/^/ /' >&2
183
+ echo "" >&2
184
+ echo " build-plugins.sh writes these, so they must be committed for this" >&2
185
+ echo " check to compare them. If one is newly generated, 'git add' it. If one" >&2
186
+ echo " is matched by .gitignore, the ignore rule is hiding a generated" >&2
187
+ echo " artifact and is the thing to fix." >&2
188
+ exit 1
189
+ fi
190
+
191
+ generated_status="$(git status --porcelain -- "${generated_files[@]}")"
192
+ if [ -n "$generated_status" ]; then
193
+ echo "✗ Generated files outside plugins/ are out of sync with their sources." >&2
194
+ echo "" >&2
195
+ echo " Files that changed after rebuilding from source:" >&2
196
+ printf "%s\n" "$generated_status" | sed 's/^/ /' >&2
197
+ echo "" >&2
198
+ echo " These are GENERATED by 'bun run build:plugins' from a canonical source" >&2
199
+ echo " elsewhere in the tree — plugins/src/base/hooks/ or scripts/. Never edit" >&2
200
+ echo " them directly; the next build overwrites the change." >&2
201
+ echo "" >&2
202
+ echo " Fix:" >&2
203
+ echo " 1. Make your edit in the canonical source, not the generated copy." >&2
204
+ echo " 2. Run: bun run build:plugins" >&2
205
+ echo " 3. Commit the regenerated copies." >&2
206
+ # Leave the tree dirty so the diff is inspectable locally; CI fails on exit.
207
+ exit 1
208
+ fi
209
+
210
+ echo "✓ ${#generated_files[@]} generated files outside plugins/ match their sources."
211
+
48
212
  # Marketplace coverage: every built plugin directory (plugins/lisa, plugins/lisa-*)
49
213
  # must be registered in .claude-plugin/marketplace.json, and every marketplace
50
214
  # entry must point at a directory that exists. The reproducibility check above