@codyswann/lisa 2.25.5 → 2.26.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.
Files changed (44) hide show
  1. package/dist/codex/hooks-installer.d.ts +7 -0
  2. package/dist/codex/hooks-installer.d.ts.map +1 -1
  3. package/dist/codex/hooks-installer.js +45 -3
  4. package/dist/codex/hooks-installer.js.map +1 -1
  5. package/dist/codex/scripts/_extract-edit-paths.sh +49 -0
  6. package/dist/codex/scripts/block-migration-edits.sh +15 -49
  7. package/dist/codex/scripts/format-on-edit.sh +26 -21
  8. package/dist/codex/scripts/lint-on-edit.sh +23 -14
  9. package/dist/codex/scripts/rubocop-on-edit.sh +23 -14
  10. package/dist/codex/scripts/sg-scan-on-edit.sh +22 -12
  11. package/package.json +1 -1
  12. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa/.codex-plugin/plugin.json +1 -2
  14. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  18. package/plugins/lisa-expo/commands/exploratory-qa.md +7 -0
  19. package/plugins/lisa-expo/skills/exploratory-qa/SKILL.md +108 -0
  20. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-harper-fabric/commands/exploratory-qa.md +7 -0
  23. package/plugins/lisa-harper-fabric/skills/exploratory-qa/SKILL.md +108 -0
  24. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -2
  26. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -2
  28. package/plugins/lisa-rails/commands/exploratory-qa.md +7 -0
  29. package/plugins/lisa-rails/skills/exploratory-qa/SKILL.md +108 -0
  30. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -2
  32. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  34. package/plugins/src/expo/commands/exploratory-qa.md +7 -0
  35. package/plugins/src/expo/skills/exploratory-qa/SKILL.md +108 -0
  36. package/plugins/src/harper-fabric/commands/exploratory-qa.md +7 -0
  37. package/plugins/src/harper-fabric/skills/exploratory-qa/SKILL.md +108 -0
  38. package/plugins/src/rails/commands/exploratory-qa.md +7 -0
  39. package/plugins/src/rails/skills/exploratory-qa/SKILL.md +108 -0
  40. package/scripts/generate-codex-plugin-artifacts.mjs +17 -129
  41. package/plugins/lisa/hooks/hooks.json +0 -104
  42. package/plugins/lisa-nestjs/hooks/hooks.json +0 -15
  43. package/plugins/lisa-rails/hooks/hooks.json +0 -19
  44. package/plugins/lisa-typescript/hooks/hooks.json +0 -23
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: exploratory-qa
3
+ description: Playwright-backed exploratory QA workflow for web apps. Use when asked to audit an app or project with Playwright/e2e tests, find human-noticeable bugs, identify gaps in automated test coverage, test responsive breakpoints, observe slow or unclear load states, exercise mutable workflows with cleanup, or produce a QA gaps report.
4
+ ---
5
+
6
+ # Exploratory QA
7
+
8
+ ## Overview
9
+
10
+ Run a human-style exploratory QA pass informed by the existing Playwright suite. The goal is to find issues users notice and machines often miss, then translate those observations into actionable Playwright coverage gaps.
11
+
12
+ ## Core Workflow
13
+
14
+ ### 1. Establish Scope
15
+
16
+ - Identify the target environment, account type, browser requirement, and requested report path.
17
+ - If credentials, tenant, seed data, or mutation boundaries are missing and cannot be discovered safely, ask a concise clarifying question.
18
+ - Treat production-like environments conservatively. Do not mutate production data unless the user explicitly approves it.
19
+ - Prefer a test user, dev/staging environment, or isolated seeded account for mutation testing.
20
+
21
+ ### 2. Research Existing Playwright Coverage
22
+
23
+ - Inspect Playwright config, auth/setup projects, fixtures, constants, selectors, test directories, skipped tests, retries, and viewport/device projects.
24
+ - Summarize:
25
+ - Number and shape of specs/tests.
26
+ - Major workflows covered well.
27
+ - Skipped/flaky/TODO coverage.
28
+ - Viewports and browser projects used.
29
+ - Mutating tests and their cleanup strategy.
30
+ - Areas where tests assert presence instead of behavior.
31
+ - Use existing test helpers/selectors when exploring the app. They reveal intended flows and stable hooks.
32
+
33
+ ### 3. Choose Browser Tools
34
+
35
+ - Use the user's requested browser/tool when specified.
36
+ - Use a real profile browser when the task depends on existing cookies, SSO, extensions, or a logged-in session.
37
+ - Use Playwright automation when exact viewport sizing, repeatable navigation, screenshots, console logs, traces, or route timing are needed.
38
+ - Do not let automation hide human observations. Screenshots, visible text, layout, latency, scrollability, and affordance clarity matter.
39
+
40
+ ### 4. Explore Like A Human
41
+
42
+ Cover at least these dimensions unless the user narrows scope:
43
+
44
+ - **Navigation:** direct URLs and visible click paths.
45
+ - **Responsive behavior:** supported breakpoints, plus boundary widths where layout changes.
46
+ - **Visual/layout quality:** cutoff text, overlap, offscreen controls, accidental horizontal scroll, empty space, awkward density, hidden stale content.
47
+ - **Load states:** blanks, skeletons, spinners, `Loading...`, `Connecting...`, delayed hydration, and whether delays exceed a human-acceptable threshold.
48
+ - **Behavior correctness:** sorting, filtering, saving, deleting, disabled states, permissions, tab persistence, URL canonicalization.
49
+ - **Accessibility/testability:** hidden or off-canvas content exposed to accessibility/text locators, duplicate inactive route content, zero-sized interactive elements.
50
+ - **Console/network health:** errors, missing assets, failed requests, noisy expected errors that could bury real failures.
51
+ - **Data hygiene:** repeated test artifacts, stale seeded content, polluted shared accounts.
52
+
53
+ ## Mutation Discipline
54
+
55
+ Exploratory QA should exercise mutable workflows when the environment is safe.
56
+
57
+ - Prefer high-value user workflows: create/edit/delete records, lists, boards, tags, notes, comments, scenarios, uploads, messages, settings, invitations, or assignments.
58
+ - Use unique names with a clear prefix such as `qa-`, `pw-`, or `codex-`.
59
+ - Before mutating, identify the cleanup path. After mutating, make a best effort to clean up through the UI, then verify cleanup.
60
+ - If UI cleanup is unavailable, record that as a product/test gap. Use documented API cleanup only if appropriate for the project and account.
61
+ - Record all mutations performed, cleanup attempts, and residue left behind.
62
+ - Avoid destructive bulk actions unless the user explicitly asks or the test account is clearly disposable.
63
+
64
+ ## Breakpoint Strategy
65
+
66
+ - Discover breakpoints from the codebase, design tokens, CSS, docs, or Playwright constants when possible.
67
+ - Test each named breakpoint and the boundary on both sides of important cutoffs.
68
+ - If breakpoints are unknown, use a practical baseline: phone, tablet/narrow, desktop, and any app-specific cutoff discovered during research.
69
+ - For each breakpoint, assert both user-visible behavior and automation-relevant state:
70
+ - Expected shell/navigation variant.
71
+ - Route-specific loaded content.
72
+ - Critical controls visible and reachable.
73
+ - No unintended document-level horizontal overflow.
74
+ - Intentional scroll containers remain usable.
75
+ - Hidden/off-canvas UI is not exposed as active content.
76
+
77
+ ## Load-State Strategy
78
+
79
+ Measure perceived latency, not just eventual success.
80
+
81
+ - Track time to shell, time to meaningful route content, and time spent in blank/loading/spinner/connecting states.
82
+ - Note when a page is technically interactive but still visually incomplete.
83
+ - Treat long waits without clear progress, error, retry, or cancellation as bugs or test gaps.
84
+ - Do not overfit exact milliseconds unless the project has defined budgets. Use practical labels such as noticeable, slow, or unacceptable and include observed durations when available.
85
+
86
+ ## Report Structure
87
+
88
+ Write the report to the user's requested path. If none is specified, use a clear local name such as `PLAYWRIGHT_GAPS.md` or `EXPLORATORY_QA_REPORT.md`.
89
+
90
+ Include:
91
+
92
+ - Scope: target URL/env, browser/tool, account type, build/version if visible, date.
93
+ - Existing Playwright coverage: strengths, thin areas, skipped tests, viewport/browser matrix, mutation coverage.
94
+ - Exploratory findings: steps, observed behavior, impact, why existing tests miss it, recommended test.
95
+ - Breakpoint findings: exact viewports tested and boundary behavior.
96
+ - Load-state findings: observed delays, blank/spinner/connecting states, suggested budgets/tests.
97
+ - Mutation findings: data created, behavior observed, cleanup attempt, cleanup result, residue.
98
+ - Missing Playwright tests to add: prioritized, concrete, and automatable.
99
+ - Maintenance notes: selector scoping, fixture cleanup, flaky/stale-state risks.
100
+
101
+ ## Quality Bar
102
+
103
+ - Be honest about what was and was not tested.
104
+ - Distinguish user-visible bugs from missing automated coverage.
105
+ - Prefer concrete examples over vague recommendations.
106
+ - Do not claim cleanup succeeded unless verified.
107
+ - Do not let broad locators pass against hidden/inactive content.
108
+ - Preserve unrelated repo changes and keep report edits scoped.
@@ -0,0 +1,7 @@
1
+ ---
2
+ description: "Run a Playwright-backed exploratory QA pass: audit the app like a human, find user-noticeable bugs and gaps in automated test coverage, and produce a QA gaps report."
3
+ allowed-tools: ["Skill"]
4
+ argument-hint: "[target-url | env] [report-path]"
5
+ ---
6
+
7
+ Use the /lisa-rails:exploratory-qa skill to run a human-style exploratory QA pass informed by the existing Playwright suite, then produce an actionable coverage-gaps report. $ARGUMENTS
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: exploratory-qa
3
+ description: Playwright-backed exploratory QA workflow for web apps. Use when asked to audit an app or project with Playwright/e2e tests, find human-noticeable bugs, identify gaps in automated test coverage, test responsive breakpoints, observe slow or unclear load states, exercise mutable workflows with cleanup, or produce a QA gaps report.
4
+ ---
5
+
6
+ # Exploratory QA
7
+
8
+ ## Overview
9
+
10
+ Run a human-style exploratory QA pass informed by the existing Playwright suite. The goal is to find issues users notice and machines often miss, then translate those observations into actionable Playwright coverage gaps.
11
+
12
+ ## Core Workflow
13
+
14
+ ### 1. Establish Scope
15
+
16
+ - Identify the target environment, account type, browser requirement, and requested report path.
17
+ - If credentials, tenant, seed data, or mutation boundaries are missing and cannot be discovered safely, ask a concise clarifying question.
18
+ - Treat production-like environments conservatively. Do not mutate production data unless the user explicitly approves it.
19
+ - Prefer a test user, dev/staging environment, or isolated seeded account for mutation testing.
20
+
21
+ ### 2. Research Existing Playwright Coverage
22
+
23
+ - Inspect Playwright config, auth/setup projects, fixtures, constants, selectors, test directories, skipped tests, retries, and viewport/device projects.
24
+ - Summarize:
25
+ - Number and shape of specs/tests.
26
+ - Major workflows covered well.
27
+ - Skipped/flaky/TODO coverage.
28
+ - Viewports and browser projects used.
29
+ - Mutating tests and their cleanup strategy.
30
+ - Areas where tests assert presence instead of behavior.
31
+ - Use existing test helpers/selectors when exploring the app. They reveal intended flows and stable hooks.
32
+
33
+ ### 3. Choose Browser Tools
34
+
35
+ - Use the user's requested browser/tool when specified.
36
+ - Use a real profile browser when the task depends on existing cookies, SSO, extensions, or a logged-in session.
37
+ - Use Playwright automation when exact viewport sizing, repeatable navigation, screenshots, console logs, traces, or route timing are needed.
38
+ - Do not let automation hide human observations. Screenshots, visible text, layout, latency, scrollability, and affordance clarity matter.
39
+
40
+ ### 4. Explore Like A Human
41
+
42
+ Cover at least these dimensions unless the user narrows scope:
43
+
44
+ - **Navigation:** direct URLs and visible click paths.
45
+ - **Responsive behavior:** supported breakpoints, plus boundary widths where layout changes.
46
+ - **Visual/layout quality:** cutoff text, overlap, offscreen controls, accidental horizontal scroll, empty space, awkward density, hidden stale content.
47
+ - **Load states:** blanks, skeletons, spinners, `Loading...`, `Connecting...`, delayed hydration, and whether delays exceed a human-acceptable threshold.
48
+ - **Behavior correctness:** sorting, filtering, saving, deleting, disabled states, permissions, tab persistence, URL canonicalization.
49
+ - **Accessibility/testability:** hidden or off-canvas content exposed to accessibility/text locators, duplicate inactive route content, zero-sized interactive elements.
50
+ - **Console/network health:** errors, missing assets, failed requests, noisy expected errors that could bury real failures.
51
+ - **Data hygiene:** repeated test artifacts, stale seeded content, polluted shared accounts.
52
+
53
+ ## Mutation Discipline
54
+
55
+ Exploratory QA should exercise mutable workflows when the environment is safe.
56
+
57
+ - Prefer high-value user workflows: create/edit/delete records, lists, boards, tags, notes, comments, scenarios, uploads, messages, settings, invitations, or assignments.
58
+ - Use unique names with a clear prefix such as `qa-`, `pw-`, or `codex-`.
59
+ - Before mutating, identify the cleanup path. After mutating, make a best effort to clean up through the UI, then verify cleanup.
60
+ - If UI cleanup is unavailable, record that as a product/test gap. Use documented API cleanup only if appropriate for the project and account.
61
+ - Record all mutations performed, cleanup attempts, and residue left behind.
62
+ - Avoid destructive bulk actions unless the user explicitly asks or the test account is clearly disposable.
63
+
64
+ ## Breakpoint Strategy
65
+
66
+ - Discover breakpoints from the codebase, design tokens, CSS, docs, or Playwright constants when possible.
67
+ - Test each named breakpoint and the boundary on both sides of important cutoffs.
68
+ - If breakpoints are unknown, use a practical baseline: phone, tablet/narrow, desktop, and any app-specific cutoff discovered during research.
69
+ - For each breakpoint, assert both user-visible behavior and automation-relevant state:
70
+ - Expected shell/navigation variant.
71
+ - Route-specific loaded content.
72
+ - Critical controls visible and reachable.
73
+ - No unintended document-level horizontal overflow.
74
+ - Intentional scroll containers remain usable.
75
+ - Hidden/off-canvas UI is not exposed as active content.
76
+
77
+ ## Load-State Strategy
78
+
79
+ Measure perceived latency, not just eventual success.
80
+
81
+ - Track time to shell, time to meaningful route content, and time spent in blank/loading/spinner/connecting states.
82
+ - Note when a page is technically interactive but still visually incomplete.
83
+ - Treat long waits without clear progress, error, retry, or cancellation as bugs or test gaps.
84
+ - Do not overfit exact milliseconds unless the project has defined budgets. Use practical labels such as noticeable, slow, or unacceptable and include observed durations when available.
85
+
86
+ ## Report Structure
87
+
88
+ Write the report to the user's requested path. If none is specified, use a clear local name such as `PLAYWRIGHT_GAPS.md` or `EXPLORATORY_QA_REPORT.md`.
89
+
90
+ Include:
91
+
92
+ - Scope: target URL/env, browser/tool, account type, build/version if visible, date.
93
+ - Existing Playwright coverage: strengths, thin areas, skipped tests, viewport/browser matrix, mutation coverage.
94
+ - Exploratory findings: steps, observed behavior, impact, why existing tests miss it, recommended test.
95
+ - Breakpoint findings: exact viewports tested and boundary behavior.
96
+ - Load-state findings: observed delays, blank/spinner/connecting states, suggested budgets/tests.
97
+ - Mutation findings: data created, behavior observed, cleanup attempt, cleanup result, residue.
98
+ - Missing Playwright tests to add: prioritized, concrete, and automatable.
99
+ - Maintenance notes: selector scoping, fixture cleanup, flaky/stale-state risks.
100
+
101
+ ## Quality Bar
102
+
103
+ - Be honest about what was and was not tested.
104
+ - Distinguish user-visible bugs from missing automated coverage.
105
+ - Prefer concrete examples over vague recommendations.
106
+ - Do not claim cleanup succeeded unless verified.
107
+ - Do not let broad locators pass against hidden/inactive content.
108
+ - Preserve unrelated repo changes and keep report edits scoped.
@@ -2,9 +2,19 @@
2
2
  /**
3
3
  * Generate Codex plugin artifacts from the built Claude plugin directories.
4
4
  *
5
- * Claude remains Lisa's production path; this script makes the Codex side
6
- * durable by deriving .codex-plugin metadata and compatible hook manifests
7
- * every time plugins are rebuilt.
5
+ * Claude remains Lisa's production path; this script derives the .codex-plugin
6
+ * metadata (skills + MCP pointers) every time plugins are rebuilt.
7
+ *
8
+ * NOTE ON HOOKS: this script does NOT emit Codex hooks. Codex (codex-cli
9
+ * 0.125.0) does not execute plugin-bundled hooks — its plugin manifest parser
10
+ * only honors `skills`, `mcpServers`, `apps`, and interface fields, and a
11
+ * runtime test confirmed a bundled `hooks/hooks.json` never fires. Lisa's
12
+ * Codex hooks are instead installed into the project's `.codex/hooks.json`
13
+ * by `src/codex/hooks-installer.ts` (run during `lisa` apply). Hooks with no
14
+ * Codex equivalent are intentionally not ported: `enforce-team-first.sh`
15
+ * (Claude-team-specific), `inject-flow-context.sh` and any SubagentStart hook
16
+ * (Codex has no SubagentStart event), and the SessionEnd `entire` hook (Codex
17
+ * has no SessionEnd event).
8
18
  */
9
19
  import fs from "node:fs";
10
20
  import path from "node:path";
@@ -29,17 +39,10 @@ if (!fs.existsSync(claudeManifestPath)) {
29
39
 
30
40
  const claudeManifest = JSON.parse(fs.readFileSync(claudeManifestPath, "utf8"));
31
41
  const pluginName = claudeManifest.name;
32
- const UNSUPPORTED_CODEX_HOOK_SCRIPTS = new Set([
33
- "hooks/enforce-team-first.sh",
34
- "hooks/inject-flow-context.sh",
35
- "hooks/inject-rules.sh",
36
- ]);
37
- const codexHooks = convertHooks(pluginName, claudeManifest.hooks ?? {});
38
42
 
39
- writeCodexManifest(pluginName, versionArg, codexHooks);
40
- writeCodexHooks(codexHooks);
43
+ writeCodexManifest(pluginName, versionArg);
41
44
 
42
- function writeCodexManifest(pluginName, version, hooksFile) {
45
+ function writeCodexManifest(pluginName, version) {
43
46
  const metadata = metadataFor(pluginName);
44
47
  const manifest = {
45
48
  name: pluginName,
@@ -50,7 +53,7 @@ function writeCodexManifest(pluginName, version, hooksFile) {
50
53
  ...(claudeManifest.dependencies
51
54
  ? { dependencies: claudeManifest.dependencies }
52
55
  : {}),
53
- ...componentPointers(hooksFile),
56
+ ...componentPointers(),
54
57
  interface: {
55
58
  displayName: metadata.displayName,
56
59
  shortDescription: metadata.shortDescription,
@@ -70,7 +73,7 @@ function writeCodexManifest(pluginName, version, hooksFile) {
70
73
  );
71
74
  }
72
75
 
73
- function componentPointers(hooksFile) {
76
+ function componentPointers() {
74
77
  return {
75
78
  ...(fs.existsSync(path.join(pluginDir, "skills"))
76
79
  ? { skills: "./skills/" }
@@ -78,124 +81,9 @@ function componentPointers(hooksFile) {
78
81
  ...(fs.existsSync(path.join(pluginDir, ".mcp.json"))
79
82
  ? { mcpServers: "./.mcp.json" }
80
83
  : {}),
81
- ...(hooksFile ? { hooks: "./hooks/hooks.json" } : {}),
82
84
  };
83
85
  }
84
86
 
85
- function writeCodexHooks(hooksFile) {
86
- const hooksDir = path.join(pluginDir, "hooks");
87
- const hooksPath = path.join(hooksDir, "hooks.json");
88
- if (!hooksFile) {
89
- if (fs.existsSync(hooksPath)) {
90
- fs.rmSync(hooksPath);
91
- }
92
- return;
93
- }
94
- fs.mkdirSync(hooksDir, { recursive: true });
95
- fs.writeFileSync(hooksPath, `${JSON.stringify(hooksFile, null, 2)}\n`);
96
- }
97
-
98
- function convertHooks(pluginName, claudeHooks) {
99
- const supportedEvents = new Set([
100
- "UserPromptSubmit",
101
- "PostToolUse",
102
- "PreToolUse",
103
- "Stop",
104
- "SessionStart",
105
- ]);
106
- const entries = Object.entries(claudeHooks)
107
- .filter(([event]) => supportedEvents.has(event))
108
- .map(([event, groups]) => [event, convertHookGroups(pluginName, groups)])
109
- .filter(([, groups]) => groups.length > 0);
110
- return entries.length > 0
111
- ? { hooks: Object.fromEntries(entries) }
112
- : undefined;
113
- }
114
-
115
- function convertHookGroups(pluginName, groups) {
116
- return groups
117
- .map(group => ({
118
- ...(group.matcher !== undefined
119
- ? { matcher: normalizeMatcher(group.matcher) }
120
- : {}),
121
- hooks: (group.hooks ?? [])
122
- .map(hook => convertHookHandler(pluginName, hook))
123
- .filter(Boolean),
124
- }))
125
- .filter(group => group.hooks.length > 0);
126
- }
127
-
128
- function normalizeMatcher(matcher) {
129
- const normalized = String(matcher).replaceAll("Write|Edit", "Edit|Write");
130
- return normalized.includes("apply_patch")
131
- ? normalized
132
- : normalized.replaceAll("Edit|Write", "Edit|Write|apply_patch");
133
- }
134
-
135
- function convertHookHandler(pluginName, hook) {
136
- if (hook.type !== "command" || typeof hook.command !== "string") {
137
- return undefined;
138
- }
139
- const command = convertHookCommand(pluginName, hook.command);
140
- if (command === undefined) {
141
- return undefined;
142
- }
143
- return {
144
- type: "command",
145
- command,
146
- ...(hook.timeout !== undefined ? { timeout: hook.timeout } : {}),
147
- ...(hook.statusMessage !== undefined
148
- ? { statusMessage: hook.statusMessage }
149
- : {}),
150
- };
151
- }
152
-
153
- function convertHookCommand(pluginName, command) {
154
- const pluginScript = command.match(
155
- /\$\{CLAUDE_PLUGIN_ROOT\}\/(hooks\/[^ "';]+)/
156
- );
157
- if (!pluginScript) {
158
- return normalizeInlineCommand(command);
159
- }
160
- if (UNSUPPORTED_CODEX_HOOK_SCRIPTS.has(pluginScript[1])) {
161
- return undefined;
162
- }
163
- return buildPluginScriptRunner(pluginName, pluginScript[1]);
164
- }
165
-
166
- function normalizeInlineCommand(command) {
167
- const entireMatch = command.match(
168
- /^command -v entire >\/dev\/null 2>&1 && entire hooks claude-code ([a-z-]+) \|\| true$/
169
- );
170
- if (!entireMatch) {
171
- return command;
172
- }
173
- return `if command -v entire >/dev/null 2>&1; then entire hooks claude-code ${entireMatch[1]}; fi`;
174
- }
175
-
176
- function buildPluginScriptRunner(pluginName, scriptPath) {
177
- const script = JSON.stringify(scriptPath);
178
- const plugin = JSON.stringify(pluginName);
179
- return [
180
- "bash -lc '",
181
- `plugin=${shellQuote(plugin)}; script=${shellQuote(script)}; `,
182
- "repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); ",
183
- 'for root in "${CODEX_PLUGIN_ROOT:-}" "${CLAUDE_PLUGIN_ROOT:-}" "$repo/plugins/$plugin" "$HOME/.codex/plugins/cache/lisa/$plugin/local"; do ',
184
- '[ -n "$root" ] || continue; ',
185
- 'if [ -x "$root/$script" ]; then CLAUDE_PLUGIN_ROOT="$root" CODEX_PLUGIN_ROOT="$root" exec "$root/$script"; fi; ',
186
- "done; ",
187
- 'found=$(find "$HOME/.codex/plugins/cache" -path "*/$plugin/*/$script" -type f -exec ls -t {} + 2>/dev/null | head -n 1); ',
188
- '[ -n "$found" ] || exit 0; ',
189
- "root=${found%/$script}; ",
190
- 'CLAUDE_PLUGIN_ROOT="$root" CODEX_PLUGIN_ROOT="$root" exec "$found"',
191
- "'",
192
- ].join("");
193
- }
194
-
195
- function shellQuote(jsonStringLiteral) {
196
- return jsonStringLiteral.replaceAll("'", "'\\''");
197
- }
198
-
199
87
  function metadataFor(pluginName) {
200
88
  const map = {
201
89
  lisa: {
@@ -1,104 +0,0 @@
1
- {
2
- "hooks": {
3
- "UserPromptSubmit": [
4
- {
5
- "matcher": "",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code user-prompt-submit; fi"
10
- }
11
- ]
12
- }
13
- ],
14
- "PostToolUse": [
15
- {
16
- "matcher": "Task",
17
- "hooks": [
18
- {
19
- "type": "command",
20
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code post-task; fi"
21
- }
22
- ]
23
- },
24
- {
25
- "matcher": "TodoWrite",
26
- "hooks": [
27
- {
28
- "type": "command",
29
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code post-todo; fi"
30
- }
31
- ]
32
- }
33
- ],
34
- "PreToolUse": [
35
- {
36
- "matcher": "Task",
37
- "hooks": [
38
- {
39
- "type": "command",
40
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code pre-task; fi"
41
- }
42
- ]
43
- },
44
- {
45
- "matcher": "Bash",
46
- "hooks": [
47
- {
48
- "type": "command",
49
- "command": "bash -lc 'plugin=\"lisa\"; script=\"hooks/block-no-verify.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
50
- }
51
- ]
52
- }
53
- ],
54
- "Stop": [
55
- {
56
- "matcher": "",
57
- "hooks": [
58
- {
59
- "type": "command",
60
- "command": "bash -lc 'plugin=\"lisa\"; script=\"hooks/notify-ntfy.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
61
- }
62
- ]
63
- },
64
- {
65
- "matcher": "",
66
- "hooks": [
67
- {
68
- "type": "command",
69
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code stop; fi"
70
- }
71
- ]
72
- }
73
- ],
74
- "SessionStart": [
75
- {
76
- "matcher": "startup",
77
- "hooks": [
78
- {
79
- "type": "command",
80
- "command": "bash -lc 'plugin=\"lisa\"; script=\"hooks/install-pkgs.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
81
- }
82
- ]
83
- },
84
- {
85
- "matcher": "",
86
- "hooks": [
87
- {
88
- "type": "command",
89
- "command": "bash -lc 'plugin=\"lisa\"; script=\"hooks/setup-jira-cli.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
90
- }
91
- ]
92
- },
93
- {
94
- "matcher": "",
95
- "hooks": [
96
- {
97
- "type": "command",
98
- "command": "if command -v entire >/dev/null 2>&1; then entire hooks claude-code session-start; fi"
99
- }
100
- ]
101
- }
102
- ]
103
- }
104
- }
@@ -1,15 +0,0 @@
1
- {
2
- "hooks": {
3
- "PreToolUse": [
4
- {
5
- "matcher": "Edit|Write|apply_patch",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "bash -lc 'plugin=\"lisa-nestjs\"; script=\"hooks/block-migration-edits.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
10
- }
11
- ]
12
- }
13
- ]
14
- }
15
- }
@@ -1,19 +0,0 @@
1
- {
2
- "hooks": {
3
- "PostToolUse": [
4
- {
5
- "matcher": "Edit|Write|apply_patch",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "bash -lc 'plugin=\"lisa-rails\"; script=\"hooks/rubocop-on-edit.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
10
- },
11
- {
12
- "type": "command",
13
- "command": "bash -lc 'plugin=\"lisa-rails\"; script=\"hooks/sg-scan-on-edit.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
14
- }
15
- ]
16
- }
17
- ]
18
- }
19
- }
@@ -1,23 +0,0 @@
1
- {
2
- "hooks": {
3
- "PostToolUse": [
4
- {
5
- "matcher": "Edit|Write|apply_patch",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "bash -lc 'plugin=\"lisa-typescript\"; script=\"hooks/format-on-edit.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
10
- },
11
- {
12
- "type": "command",
13
- "command": "bash -lc 'plugin=\"lisa-typescript\"; script=\"hooks/sg-scan-on-edit.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
14
- },
15
- {
16
- "type": "command",
17
- "command": "bash -lc 'plugin=\"lisa-typescript\"; script=\"hooks/lint-on-edit.sh\"; repo=$(git rev-parse --show-toplevel 2>/dev/null || pwd); for root in \"${CODEX_PLUGIN_ROOT:-}\" \"${CLAUDE_PLUGIN_ROOT:-}\" \"$repo/plugins/$plugin\" \"$HOME/.codex/plugins/cache/lisa/$plugin/local\"; do [ -n \"$root\" ] || continue; if [ -x \"$root/$script\" ]; then CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$root/$script\"; fi; done; found=$(find \"$HOME/.codex/plugins/cache\" -path \"*/$plugin/*/$script\" -type f -exec ls -t {} + 2>/dev/null | head -n 1); [ -n \"$found\" ] || exit 0; root=${found%/$script}; CLAUDE_PLUGIN_ROOT=\"$root\" CODEX_PLUGIN_ROOT=\"$root\" exec \"$found\"'"
18
- }
19
- ]
20
- }
21
- ]
22
- }
23
- }