@codyswann/lisa 2.26.0 → 2.26.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.
- package/dist/codex/hooks-installer.d.ts +7 -0
- package/dist/codex/hooks-installer.d.ts.map +1 -1
- package/dist/codex/hooks-installer.js +45 -3
- package/dist/codex/hooks-installer.js.map +1 -1
- package/dist/codex/scripts/_extract-edit-paths.sh +49 -0
- package/dist/codex/scripts/block-migration-edits.sh +15 -49
- package/dist/codex/scripts/format-on-edit.sh +26 -21
- package/dist/codex/scripts/lint-on-edit.sh +23 -14
- package/dist/codex/scripts/rubocop-on-edit.sh +23 -14
- package/dist/codex/scripts/sg-scan-on-edit.sh +22 -12
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -2
- package/plugins/lisa/rules/base-rules.md +1 -1
- package/plugins/lisa/skills/debrief/SKILL.md +9 -3
- package/plugins/lisa/skills/implement/SKILL.md +10 -4
- package/plugins/lisa/skills/intake/SKILL.md +9 -3
- package/plugins/lisa/skills/monitor/SKILL.md +9 -3
- package/plugins/lisa/skills/plan/SKILL.md +9 -3
- package/plugins/lisa/skills/research/SKILL.md +9 -3
- package/plugins/lisa/skills/verify/SKILL.md +9 -3
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-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-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -2
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -2
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -2
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/base-rules.md +1 -1
- package/plugins/src/base/skills/debrief/SKILL.md +9 -3
- package/plugins/src/base/skills/implement/SKILL.md +10 -4
- package/plugins/src/base/skills/intake/SKILL.md +9 -3
- package/plugins/src/base/skills/monitor/SKILL.md +9 -3
- package/plugins/src/base/skills/plan/SKILL.md +9 -3
- package/plugins/src/base/skills/research/SKILL.md +9 -3
- package/plugins/src/base/skills/verify/SKILL.md +9 -3
- package/scripts/generate-codex-plugin-artifacts.mjs +17 -129
- package/plugins/lisa/hooks/hooks.json +0 -104
- package/plugins/lisa-nestjs/hooks/hooks.json +0 -15
- package/plugins/lisa-rails/hooks/hooks.json +0 -19
- package/plugins/lisa-typescript/hooks/hooks.json +0 -23
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { ProjectType } from "../core/config.js";
|
|
2
2
|
/** Subdirectory inside `.codex/` for Lisa-managed hook scripts */
|
|
3
3
|
export declare const LISA_HOOKS_SUBDIR: string;
|
|
4
|
+
/**
|
|
5
|
+
* Shared shell helper sourced by every edit-aware hook to resolve the file
|
|
6
|
+
* path(s) a tool touches (handles single-file Edit/Write and multi-file
|
|
7
|
+
* apply_patch). Copied alongside the hook scripts whenever an edit hook is
|
|
8
|
+
* installed so the apply_patch parsing lives in exactly one place.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EDIT_PATHS_LIB = "_extract-edit-paths.sh";
|
|
4
11
|
/** Subdirectory inside `.codex/` for Lisa rules content (read by inject-rules) */
|
|
5
12
|
export declare const LISA_RULES_SUBDIR = "lisa-rules";
|
|
6
13
|
/** Filename of the Codex hooks config file inside `.codex/` */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-installer.d.ts","sourceRoot":"","sources":["../../src/codex/hooks-installer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks-installer.d.ts","sourceRoot":"","sources":["../../src/codex/hooks-installer.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUrD,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,QAA6B,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAE9C,+DAA+D;AAC/D,eAAO,MAAM,cAAc,eAAe,CAAC;AA0H3C,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,SAAS,WAAW,EAAE,GACpC,OAAO,CAAC,kBAAkB,CAAC,CA4D7B"}
|
|
@@ -7,10 +7,24 @@
|
|
|
7
7
|
* 3. For inject-rules: also mirror Lisa rules into `.codex/lisa-rules/`
|
|
8
8
|
* 4. Tagged-merge `.codex/hooks.json`
|
|
9
9
|
*
|
|
10
|
-
* Codex hook event support map (vs. Lisa's existing Claude Code hooks)
|
|
10
|
+
* Codex hook event support map (vs. Lisa's existing Claude Code hooks),
|
|
11
|
+
* verified against codex-cli 0.125.0 by source-read + runtime tests:
|
|
11
12
|
* - SessionStart, PreToolUse, PostToolUse, UserPromptSubmit, Stop ✅
|
|
12
13
|
* - PermissionRequest ✅ (Codex-only)
|
|
13
14
|
* - SubagentStart, SessionEnd, Notification, PreCompact ❌ (Codex doesn't have these)
|
|
15
|
+
*
|
|
16
|
+
* Claude hooks intentionally NOT ported (no Codex equivalent):
|
|
17
|
+
* - enforce-team-first.sh — gates Claude's TeamCreate/Skill/ToolSearch agent-
|
|
18
|
+
* team orchestration; Codex's multi-agent model is different.
|
|
19
|
+
* - inject-flow-context.sh — fires on SubagentStart, which Codex lacks.
|
|
20
|
+
* - the SessionEnd `entire` hook — Codex has no SessionEnd event.
|
|
21
|
+
* inject-rules also fires on SubagentStart under Claude; on Codex only its
|
|
22
|
+
* SessionStart variant applies (Codex has no per-subagent start event).
|
|
23
|
+
*
|
|
24
|
+
* Codex does NOT execute plugin-bundled hooks (a `.codex-plugin` `hooks`
|
|
25
|
+
* pointer / `hooks/hooks.json` never fires), so this installer writes hooks
|
|
26
|
+
* into the project's own `.codex/hooks.json` instead. See
|
|
27
|
+
* scripts/generate-codex-plugin-artifacts.mjs for the build-side counterpart.
|
|
14
28
|
* @module codex/hooks-installer
|
|
15
29
|
*/
|
|
16
30
|
import * as fse from "fs-extra";
|
|
@@ -20,6 +34,13 @@ import { fileURLToPath } from "node:url";
|
|
|
20
34
|
import { mergeLisaHooks, parseHooksFile, serializeHooksFile, } from "./hooks-merger.js";
|
|
21
35
|
/** Subdirectory inside `.codex/` for Lisa-managed hook scripts */
|
|
22
36
|
export const LISA_HOOKS_SUBDIR = path.join("hooks", "lisa");
|
|
37
|
+
/**
|
|
38
|
+
* Shared shell helper sourced by every edit-aware hook to resolve the file
|
|
39
|
+
* path(s) a tool touches (handles single-file Edit/Write and multi-file
|
|
40
|
+
* apply_patch). Copied alongside the hook scripts whenever an edit hook is
|
|
41
|
+
* installed so the apply_patch parsing lives in exactly one place.
|
|
42
|
+
*/
|
|
43
|
+
export const EDIT_PATHS_LIB = "_extract-edit-paths.sh";
|
|
23
44
|
/** Subdirectory inside `.codex/` for Lisa rules content (read by inject-rules) */
|
|
24
45
|
export const LISA_RULES_SUBDIR = "lisa-rules";
|
|
25
46
|
/** Filename of the Codex hooks config file inside `.codex/` */
|
|
@@ -85,6 +106,7 @@ const HOOK_CATALOG = [
|
|
|
85
106
|
matcher: WRITE_MATCHER,
|
|
86
107
|
scriptFilename: "format-on-edit.sh",
|
|
87
108
|
forProjectTypes: ["typescript"],
|
|
109
|
+
needsEditPathLib: true,
|
|
88
110
|
},
|
|
89
111
|
{
|
|
90
112
|
id: "lint-on-edit",
|
|
@@ -92,13 +114,15 @@ const HOOK_CATALOG = [
|
|
|
92
114
|
matcher: WRITE_MATCHER,
|
|
93
115
|
scriptFilename: "lint-on-edit.sh",
|
|
94
116
|
forProjectTypes: ["typescript"],
|
|
117
|
+
needsEditPathLib: true,
|
|
95
118
|
},
|
|
96
119
|
{
|
|
97
120
|
id: "sg-scan-on-edit",
|
|
98
121
|
event: "PostToolUse",
|
|
99
122
|
matcher: WRITE_MATCHER,
|
|
100
123
|
scriptFilename: "sg-scan-on-edit.sh",
|
|
101
|
-
forProjectTypes: ["typescript"],
|
|
124
|
+
forProjectTypes: ["typescript", "rails"],
|
|
125
|
+
needsEditPathLib: true,
|
|
102
126
|
},
|
|
103
127
|
{
|
|
104
128
|
id: "rubocop-on-edit",
|
|
@@ -106,6 +130,7 @@ const HOOK_CATALOG = [
|
|
|
106
130
|
matcher: WRITE_MATCHER,
|
|
107
131
|
scriptFilename: "rubocop-on-edit.sh",
|
|
108
132
|
forProjectTypes: ["rails"],
|
|
133
|
+
needsEditPathLib: true,
|
|
109
134
|
},
|
|
110
135
|
{
|
|
111
136
|
id: "block-migration-edits",
|
|
@@ -113,6 +138,7 @@ const HOOK_CATALOG = [
|
|
|
113
138
|
matcher: WRITE_MATCHER,
|
|
114
139
|
scriptFilename: "block-migration-edits.sh",
|
|
115
140
|
forProjectTypes: ["nestjs"],
|
|
141
|
+
needsEditPathLib: true,
|
|
116
142
|
},
|
|
117
143
|
];
|
|
118
144
|
/**
|
|
@@ -138,6 +164,17 @@ export async function installHooks(lisaDir, destDir, detectedTypes) {
|
|
|
138
164
|
await chmod(scriptDest, 0o755);
|
|
139
165
|
return path.join(LISA_HOOKS_SUBDIR, entry.scriptFilename);
|
|
140
166
|
}));
|
|
167
|
+
// Step 1b: copy the shared edit-path helper when any installed hook sources
|
|
168
|
+
// it. Edit-aware hooks (format/lint/sg-scan/rubocop/block-migration) source
|
|
169
|
+
// this for apply_patch path parsing.
|
|
170
|
+
const libFiles = applicable.some(e => e.needsEditPathLib)
|
|
171
|
+
? await (async () => {
|
|
172
|
+
const libDest = path.join(hooksDir, EDIT_PATHS_LIB);
|
|
173
|
+
await copyFile(resolveBundledScript(EDIT_PATHS_LIB), libDest);
|
|
174
|
+
await chmod(libDest, 0o755);
|
|
175
|
+
return [path.join(LISA_HOOKS_SUBDIR, EDIT_PATHS_LIB)];
|
|
176
|
+
})()
|
|
177
|
+
: [];
|
|
141
178
|
// Step 2: mirror rules from Lisa into .codex/lisa-rules/ (only when
|
|
142
179
|
// inject-rules is being installed — i.e., always, since it's a "*" hook)
|
|
143
180
|
const ruleFiles = applicable.some(e => e.id === "inject-rules")
|
|
@@ -150,7 +187,12 @@ export async function installHooks(lisaDir, destDir, detectedTypes) {
|
|
|
150
187
|
const merged = mergeLisaHooks(existing, lisaHookSpecs);
|
|
151
188
|
await writeFile(hooksFilePath, serializeHooksFile(merged), "utf8");
|
|
152
189
|
return {
|
|
153
|
-
managedFiles: Object.freeze([
|
|
190
|
+
managedFiles: Object.freeze([
|
|
191
|
+
...scriptFiles,
|
|
192
|
+
...libFiles,
|
|
193
|
+
...ruleFiles,
|
|
194
|
+
HOOKS_FILENAME,
|
|
195
|
+
]),
|
|
154
196
|
hookEntries: lisaHookSpecs.length,
|
|
155
197
|
};
|
|
156
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-installer.js","sourceRoot":"","sources":["../../src/codex/hooks-installer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks-installer.js","sourceRoot":"","sources":["../../src/codex/hooks-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Lisa-managed Codex hook helper (sourced, not executed directly).
|
|
3
|
+
#
|
|
4
|
+
# Provides `lisa_extract_edit_paths`, the single source of truth for turning a
|
|
5
|
+
# Codex Pre/PostToolUse hook envelope into the list of file paths the tool
|
|
6
|
+
# touches. Every edit-aware Lisa hook (format/lint/sg-scan/rubocop/block-
|
|
7
|
+
# migration) sources this so the apply_patch parsing lives in exactly one place.
|
|
8
|
+
#
|
|
9
|
+
# Tool envelope shapes (verified against codex-cli 0.125.0 by capturing real
|
|
10
|
+
# hook stdin):
|
|
11
|
+
# Edit / Write → tool_input.file_path (single string)
|
|
12
|
+
# apply_patch → tool_input.command (a STRING containing the full patch,
|
|
13
|
+
# NOT an array — there is no command[1])
|
|
14
|
+
#
|
|
15
|
+
# An apply_patch patch encodes its targets as header lines:
|
|
16
|
+
# *** Add File: <path>
|
|
17
|
+
# *** Update File: <path>
|
|
18
|
+
# *** Delete File: <path>
|
|
19
|
+
# A single patch may carry MANY files, so callers must loop over the output.
|
|
20
|
+
|
|
21
|
+
# Print, one per line, every file path the tool envelope intends to write.
|
|
22
|
+
# Emits nothing (and returns 0) when jq is unavailable or no path is found, so
|
|
23
|
+
# callers can fail open.
|
|
24
|
+
#
|
|
25
|
+
# $1 - the full hook stdin JSON
|
|
26
|
+
lisa_extract_edit_paths() {
|
|
27
|
+
local json="$1"
|
|
28
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
29
|
+
|
|
30
|
+
local tool_name
|
|
31
|
+
tool_name="$(printf '%s' "$json" | jq -r '.tool_name // .tool // empty')"
|
|
32
|
+
|
|
33
|
+
if [ "$tool_name" = "apply_patch" ]; then
|
|
34
|
+
local patch_text
|
|
35
|
+
patch_text="$(printf '%s' "$json" | jq -r '.tool_input.command // empty')"
|
|
36
|
+
[ -n "$patch_text" ] || return 0
|
|
37
|
+
# Walk the patch line-by-line with bash-native string ops (NOT grep/sed on
|
|
38
|
+
# JSON — see .claude/rules/PROJECT_RULES.md) to pull out every file header.
|
|
39
|
+
while IFS= read -r line; do
|
|
40
|
+
case "$line" in
|
|
41
|
+
"*** Add File: "* | "*** Update File: "* | "*** Delete File: "*)
|
|
42
|
+
printf '%s\n' "${line#*File: }"
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
done <<<"$patch_text"
|
|
46
|
+
else
|
|
47
|
+
printf '%s' "$json" | jq -r '.tool_input.file_path // empty'
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
@@ -4,59 +4,23 @@
|
|
|
4
4
|
# to regenerate from entity diffs instead — hand-written migrations drift
|
|
5
5
|
# from entity metadata and break the schema/migration contract.
|
|
6
6
|
#
|
|
7
|
-
# Codex blocks the tool call when
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
# apply_patch → tool_input.command (["apply_patch", "<patch>"])
|
|
13
|
-
#
|
|
14
|
-
# The patch text encodes target file paths via "*** Update File: <path>" /
|
|
15
|
-
# "*** Add File: <path>" / "*** Delete File: <path>" directives. We must
|
|
16
|
-
# extract every such path so apply_patch can't sneak past this guard.
|
|
17
|
-
set -euo pipefail
|
|
7
|
+
# Codex blocks the tool call when the script exits non-zero with a deny message
|
|
8
|
+
# on stderr (exit 2). The shared extractor resolves every target path from the
|
|
9
|
+
# tool envelope — including multi-file apply_patch patches — so an edit can't
|
|
10
|
+
# slip a migration change past this guard.
|
|
11
|
+
set -uo pipefail
|
|
18
12
|
|
|
19
13
|
JSON_INPUT="$(cat)"
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
exit 0
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
# Determine which tool fired. Codex puts the tool name at .tool_name on
|
|
28
|
-
# every PreToolUse envelope; falling back to .tool just in case.
|
|
29
|
-
TOOL_NAME="$(echo "$JSON_INPUT" | jq -r '.tool_name // .tool // empty')"
|
|
15
|
+
# Without jq we can't reliably parse — fail open (allow the edit). This matches
|
|
16
|
+
# the project rule against grep/sed/cut/awk-based JSON parsing.
|
|
17
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
apply_patch)
|
|
35
|
-
# Pull the full patch string out of tool_input.command[1], then extract
|
|
36
|
-
# every "*** {Update,Add,Delete} File: <path>" header line. jq handles
|
|
37
|
-
# the JSON; we use bash-native string splitting (NOT grep/cut on JSON)
|
|
38
|
-
# to walk the patch text line-by-line.
|
|
39
|
-
PATCH_TEXT="$(echo "$JSON_INPUT" | jq -r '.tool_input.command[1] // empty')"
|
|
40
|
-
if [ -n "${PATCH_TEXT}" ]; then
|
|
41
|
-
while IFS= read -r line; do
|
|
42
|
-
case "$line" in
|
|
43
|
-
"*** Update File: "*|"*** Add File: "*|"*** Delete File: "*)
|
|
44
|
-
CANDIDATE_PATHS+="${line#*: }"$'\n'
|
|
45
|
-
;;
|
|
46
|
-
esac
|
|
47
|
-
done <<<"${PATCH_TEXT}"
|
|
48
|
-
fi
|
|
49
|
-
;;
|
|
50
|
-
*)
|
|
51
|
-
# Edit / Write / anything else: single file under tool_input.file_path
|
|
52
|
-
SINGLE_PATH="$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')"
|
|
53
|
-
[ -n "${SINGLE_PATH}" ] && CANDIDATE_PATHS="${SINGLE_PATH}"
|
|
54
|
-
;;
|
|
55
|
-
esac
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
# shellcheck source=/dev/null
|
|
21
|
+
. "${SCRIPT_DIR}/_extract-edit-paths.sh"
|
|
56
22
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# Walk every candidate; deny on the first migration match.
|
|
23
|
+
# Walk every candidate path; deny on the first migration match.
|
|
60
24
|
while IFS= read -r FILE_PATH; do
|
|
61
25
|
[ -n "${FILE_PATH}" ] || continue
|
|
62
26
|
case "${FILE_PATH}" in
|
|
@@ -73,6 +37,8 @@ EOF
|
|
|
73
37
|
exit 2
|
|
74
38
|
;;
|
|
75
39
|
esac
|
|
76
|
-
done
|
|
40
|
+
done <<EOF
|
|
41
|
+
$(lisa_extract_edit_paths "$JSON_INPUT")
|
|
42
|
+
EOF
|
|
77
43
|
|
|
78
44
|
exit 0
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Lisa-managed Codex hook script (PostToolUse Edit|Write|apply_patch).
|
|
3
|
-
# Runs Prettier on
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
# under tool_input.command (an array), not tool_input.file_path. This script
|
|
8
|
-
# only formats single-file Edit/Write tool calls. apply_patch fires get
|
|
9
|
-
# silently skipped (FILE_PATH empty) — that's acceptable here because the
|
|
10
|
-
# next save/edit will still run the formatter, and the user can always run
|
|
11
|
-
# `prettier --write` against modified files manually.
|
|
12
|
-
set -euo pipefail
|
|
3
|
+
# Runs Prettier on every just-edited file. Resolves the target file(s) from the
|
|
4
|
+
# tool envelope via the shared extractor, which handles both single-file
|
|
5
|
+
# Edit/Write (tool_input.file_path) and multi-file apply_patch (tool_input.command).
|
|
6
|
+
set -uo pipefail
|
|
13
7
|
|
|
14
8
|
JSON_INPUT="$(cat)"
|
|
15
9
|
|
|
@@ -17,19 +11,30 @@ JSON_INPUT="$(cat)"
|
|
|
17
11
|
# with grep/sed/cut/awk — always use jq. Fail open without jq so we don't
|
|
18
12
|
# block the agent on missing tooling.
|
|
19
13
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
20
|
-
FILE_PATH="$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')"
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
# shellcheck source=/dev/null
|
|
17
|
+
. "${SCRIPT_DIR}/_extract-edit-paths.sh"
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
ts|tsx|js|jsx|mjs|cjs|json|md|yaml|yml|css|scss|html) ;;
|
|
27
|
-
*) exit 0 ;;
|
|
28
|
-
esac
|
|
29
|
-
|
|
30
|
-
# Prefer the project-local prettier; fall back to a globally installed one
|
|
19
|
+
# Resolve the formatter once, up front.
|
|
31
20
|
if [ -x "./node_modules/.bin/prettier" ]; then
|
|
32
|
-
./node_modules/.bin/prettier
|
|
21
|
+
PRETTIER="./node_modules/.bin/prettier"
|
|
33
22
|
elif command -v prettier >/dev/null 2>&1; then
|
|
34
|
-
prettier
|
|
23
|
+
PRETTIER="prettier"
|
|
24
|
+
else
|
|
25
|
+
exit 0
|
|
35
26
|
fi
|
|
27
|
+
|
|
28
|
+
while IFS= read -r FILE_PATH; do
|
|
29
|
+
[ -n "${FILE_PATH}" ] || continue
|
|
30
|
+
[ -f "${FILE_PATH}" ] || continue
|
|
31
|
+
case "${FILE_PATH##*.}" in
|
|
32
|
+
ts | tsx | js | jsx | mjs | cjs | json | md | yaml | yml | css | scss | html) ;;
|
|
33
|
+
*) continue ;;
|
|
34
|
+
esac
|
|
35
|
+
"$PRETTIER" --write "${FILE_PATH}" >/dev/null 2>&1 || true
|
|
36
|
+
done <<EOF
|
|
37
|
+
$(lisa_extract_edit_paths "$JSON_INPUT")
|
|
38
|
+
EOF
|
|
39
|
+
|
|
40
|
+
exit 0
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Lisa-managed Codex hook script (PostToolUse Edit|Write|apply_patch).
|
|
3
|
-
# Runs ESLint --fix on
|
|
4
|
-
# exits non-zero so Codex sees the failure and the agent self-corrects.
|
|
5
|
-
|
|
3
|
+
# Runs ESLint --fix on every just-edited file. If unfixable errors remain on
|
|
4
|
+
# any file, exits non-zero so Codex sees the failure and the agent self-corrects.
|
|
5
|
+
# Resolves target file(s) via the shared extractor (Edit/Write + apply_patch).
|
|
6
|
+
set -uo pipefail
|
|
6
7
|
|
|
7
8
|
JSON_INPUT="$(cat)"
|
|
8
9
|
|
|
9
10
|
# Project rule (.claude/rules/PROJECT_RULES.md): never parse JSON in shell
|
|
10
11
|
# with grep/sed/cut/awk — always use jq. Fail open without jq.
|
|
11
12
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
12
|
-
FILE_PATH="$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')"
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
case "${FILE_PATH##*.}" in
|
|
18
|
-
ts|tsx|js|jsx|mjs|cjs) ;;
|
|
19
|
-
*) exit 0 ;;
|
|
20
|
-
esac
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
# shellcheck source=/dev/null
|
|
16
|
+
. "${SCRIPT_DIR}/_extract-edit-paths.sh"
|
|
21
17
|
|
|
22
18
|
if [ -x "./node_modules/.bin/eslint" ]; then
|
|
23
19
|
ESLINT="./node_modules/.bin/eslint"
|
|
@@ -27,6 +23,19 @@ else
|
|
|
27
23
|
exit 0
|
|
28
24
|
fi
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
STATUS=0
|
|
27
|
+
while IFS= read -r FILE_PATH; do
|
|
28
|
+
[ -n "${FILE_PATH}" ] || continue
|
|
29
|
+
[ -f "${FILE_PATH}" ] || continue
|
|
30
|
+
case "${FILE_PATH##*.}" in
|
|
31
|
+
ts | tsx | js | jsx | mjs | cjs) ;;
|
|
32
|
+
*) continue ;;
|
|
33
|
+
esac
|
|
34
|
+
# Auto-fix what we can; surface anything left so the agent fixes it itself.
|
|
35
|
+
"$ESLINT" --fix "${FILE_PATH}" >/dev/null 2>&1 || true
|
|
36
|
+
"$ESLINT" --quiet "${FILE_PATH}" || STATUS=1
|
|
37
|
+
done <<EOF
|
|
38
|
+
$(lisa_extract_edit_paths "$JSON_INPUT")
|
|
39
|
+
EOF
|
|
40
|
+
|
|
41
|
+
exit "$STATUS"
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Lisa-managed Codex hook script (PostToolUse Edit|Write|apply_patch).
|
|
3
|
-
# Runs RuboCop -a (safe autocorrect) on
|
|
4
|
-
#
|
|
5
|
-
# the agent to fix.
|
|
6
|
-
|
|
3
|
+
# Runs RuboCop -a (safe autocorrect) on every just-edited Ruby file, then checks
|
|
4
|
+
# for remaining unfixable errors. Blocking — a non-zero exit on any file forces
|
|
5
|
+
# the agent to fix. Resolves target file(s) via the shared extractor
|
|
6
|
+
# (Edit/Write + apply_patch).
|
|
7
|
+
set -uo pipefail
|
|
7
8
|
|
|
8
9
|
JSON_INPUT="$(cat)"
|
|
9
10
|
|
|
10
11
|
# Project rule (.claude/rules/PROJECT_RULES.md): never parse JSON in shell
|
|
11
12
|
# with grep/sed/cut/awk — always use jq. Fail open without jq.
|
|
12
13
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
13
|
-
FILE_PATH="$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')"
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
case "${FILE_PATH##*.}" in
|
|
19
|
-
rb|rake) ;;
|
|
20
|
-
*) exit 0 ;;
|
|
21
|
-
esac
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
# shellcheck source=/dev/null
|
|
17
|
+
. "${SCRIPT_DIR}/_extract-edit-paths.sh"
|
|
22
18
|
|
|
23
19
|
if command -v bundle >/dev/null 2>&1 && [ -f "./Gemfile" ]; then
|
|
24
20
|
RUBOCOP=(bundle exec rubocop)
|
|
@@ -28,5 +24,18 @@ else
|
|
|
28
24
|
exit 0
|
|
29
25
|
fi
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
STATUS=0
|
|
28
|
+
while IFS= read -r FILE_PATH; do
|
|
29
|
+
[ -n "${FILE_PATH}" ] || continue
|
|
30
|
+
[ -f "${FILE_PATH}" ] || continue
|
|
31
|
+
case "${FILE_PATH##*.}" in
|
|
32
|
+
rb | rake) ;;
|
|
33
|
+
*) continue ;;
|
|
34
|
+
esac
|
|
35
|
+
"${RUBOCOP[@]}" -a "${FILE_PATH}" >/dev/null 2>&1 || true
|
|
36
|
+
"${RUBOCOP[@]}" "${FILE_PATH}" || STATUS=1
|
|
37
|
+
done <<EOF
|
|
38
|
+
$(lisa_extract_edit_paths "$JSON_INPUT")
|
|
39
|
+
EOF
|
|
40
|
+
|
|
41
|
+
exit "$STATUS"
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Lisa-managed Codex hook script (PostToolUse Edit|Write|apply_patch).
|
|
3
|
-
# Runs ast-grep scan
|
|
4
|
-
#
|
|
5
|
-
|
|
3
|
+
# Runs ast-grep scan on every just-edited source file (TypeScript/JS or Ruby),
|
|
4
|
+
# reporting only errors involving those files. Blocking — a non-zero exit on any
|
|
5
|
+
# file forces the agent to fix. Resolves target file(s) via the shared extractor
|
|
6
|
+
# (Edit/Write + apply_patch).
|
|
7
|
+
set -uo pipefail
|
|
6
8
|
|
|
7
9
|
JSON_INPUT="$(cat)"
|
|
8
10
|
|
|
9
11
|
# Project rule (.claude/rules/PROJECT_RULES.md): never parse JSON in shell
|
|
10
12
|
# with grep/sed/cut/awk — always use jq. Fail open without jq.
|
|
11
13
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
12
|
-
FILE_PATH="$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || true)"
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
case "${FILE_PATH##*.}" in
|
|
18
|
-
ts|tsx|js|jsx|mjs|cjs) ;;
|
|
19
|
-
*) exit 0 ;;
|
|
20
|
-
esac
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
# shellcheck source=/dev/null
|
|
17
|
+
. "${SCRIPT_DIR}/_extract-edit-paths.sh"
|
|
21
18
|
|
|
22
19
|
if [ -x "./node_modules/.bin/ast-grep" ]; then
|
|
23
20
|
AST_GREP="./node_modules/.bin/ast-grep"
|
|
@@ -31,4 +28,17 @@ fi
|
|
|
31
28
|
|
|
32
29
|
[ -f "./sgconfig.yml" ] || exit 0
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
STATUS=0
|
|
32
|
+
while IFS= read -r FILE_PATH; do
|
|
33
|
+
[ -n "${FILE_PATH}" ] || continue
|
|
34
|
+
[ -f "${FILE_PATH}" ] || continue
|
|
35
|
+
case "${FILE_PATH##*.}" in
|
|
36
|
+
ts | tsx | js | jsx | mjs | cjs | rb | rake) ;;
|
|
37
|
+
*) continue ;;
|
|
38
|
+
esac
|
|
39
|
+
"$AST_GREP" scan "${FILE_PATH}" 2>&1 || STATUS=1
|
|
40
|
+
done <<EOF
|
|
41
|
+
$(lisa_extract_edit_paths "$JSON_INPUT")
|
|
42
|
+
EOF
|
|
43
|
+
|
|
44
|
+
exit "$STATUS"
|
package/package.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"lodash": ">=4.18.1"
|
|
83
83
|
},
|
|
84
84
|
"name": "@codyswann/lisa",
|
|
85
|
-
"version": "2.26.
|
|
85
|
+
"version": "2.26.2",
|
|
86
86
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
87
87
|
"main": "dist/index.js",
|
|
88
88
|
"exports": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa",
|
|
3
|
-
"version": "2.26.
|
|
3
|
+
"version": "2.26.2",
|
|
4
4
|
"description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"workflow"
|
|
13
13
|
],
|
|
14
14
|
"skills": "./skills/",
|
|
15
|
-
"hooks": "./hooks/hooks.json",
|
|
16
15
|
"interface": {
|
|
17
16
|
"displayName": "Lisa",
|
|
18
17
|
"shortDescription": "Universal project governance workflows",
|
|
@@ -8,7 +8,7 @@ After echoing the chosen flow and BEFORE doing any work, state the orchestration
|
|
|
8
8
|
|
|
9
9
|
Default to an agent team for Research, Plan, Implement (Build/Fix/Improve/Investigate-Only), and any flow that invokes the Review sub-flow. Use a single agent only for Verify (standalone) and Monitor (standalone). See the `intent-routing` rule's Orchestration section for the full decision matrix.
|
|
10
10
|
|
|
11
|
-
When the mode is `agent team` **and you are not already operating inside an agent team**, your FIRST tool calls after the classification echo MUST establish team orchestration before any content-gathering work. Use
|
|
11
|
+
When the mode is `agent team` **and you are not already operating inside an agent team**, your FIRST tool calls after the classification echo MUST establish team orchestration before any content-gathering work. Use the team tool for the current runtime: Claude uses `TeamCreate` (first `ToolSearch` with `query: "select:TeamCreate"` if needed); Codex must not call `TeamCreate` because Codex does not expose that Claude tool. In Codex, use `tool_search` with a query like `multi-agent tools` to load `multi_agent_v1`, then use `multi_agent_v1.spawn_agent` for teammate delegation and treat the first successful `spawn_agent` call as establishing team orchestration. Other runtimes should use their current tool-discovery mechanism to discover and call the appropriate multi-agent/team tool. If no team creation or subagent delegation tool is available, explicitly state that team orchestration is unavailable in this runtime, continue as the lead agent, and preserve the workflow's review, verification, and task-tracking obligations locally. Do not reach for `TaskCreate`, `Agent`, `Skill`, MCP tools, `Read`, `Bash`, or any other content-gathering call before the team exists, the first Codex teammate has been spawned, or the no-team fallback has been declared — those are bypass paths that skip durable task state and parallel review. Reading the ticket, exploring the code, querying the API are all tasks for the team, not for the lead session before orchestration exists.
|
|
12
12
|
|
|
13
13
|
Requirement Verification:
|
|
14
14
|
|
|
@@ -10,11 +10,17 @@ Walk the original Plan for `$ARGUMENTS`, mine the completed work items and their
|
|
|
10
10
|
|
|
11
11
|
## Orchestration: agent team
|
|
12
12
|
|
|
13
|
-
If you are NOT already operating inside an agent team (no prior successful team-creation tool call in this session, not spawned into a team context), the very first thing you do is establish team orchestration.
|
|
13
|
+
If you are NOT already operating inside an agent team (no prior successful team-creation or subagent-delegation tool call in this session, not spawned into a team context), the very first thing you do is establish team orchestration.
|
|
14
14
|
|
|
15
|
-
Use
|
|
15
|
+
Use the team tool for the current runtime:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
- Claude: use `TeamCreate`. If `TeamCreate` has not been loaded yet, first use `ToolSearch` with `query: "select:TeamCreate"` to load its schema.
|
|
18
|
+
- Codex: do not call `TeamCreate`; Codex does not expose that Claude tool. Use `tool_search` with a query like `multi-agent tools` to load `multi_agent_v1`, then use `multi_agent_v1.spawn_agent` for teammate delegation. Treat the first successful `spawn_agent` call as establishing team orchestration.
|
|
19
|
+
- Other runtimes: use the current runtime's tool-discovery mechanism to discover and call the appropriate multi-agent/team tool.
|
|
20
|
+
|
|
21
|
+
If no team creation or subagent delegation tool is available, explicitly state that team orchestration is unavailable in this runtime, continue as the lead agent, and preserve the workflow's review, verification, and task-tracking obligations locally.
|
|
22
|
+
|
|
23
|
+
Until the team is established, the first Codex teammate has been spawned, or the no-team fallback has been declared, do NOT call any of: `Agent`, `TaskCreate`, `Skill`, MCP tools (Atlassian / Linear / GitHub / Notion), `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`. Resolving the work-item set, fetching tickets, walking PRs — all of those are tasks for the team you are about to create, not for the lead session before orchestration exists.
|
|
18
24
|
|
|
19
25
|
If you ARE already inside an agent team (e.g., a teammate invoked this skill via the Skill tool), do NOT create a second team — many harnesses reject double-creates. Continue within the existing team.
|
|
20
26
|
|
|
@@ -7,13 +7,19 @@ description: This skill should be used for any non-trivial request — features,
|
|
|
7
7
|
|
|
8
8
|
## Orchestration: agent team
|
|
9
9
|
|
|
10
|
-
Implement is a **team-first** flow. Bug, Build, Improve, and Investigate-Only all compose multiple specialists (Reproduce → debug → fix → review → verify). Single-agent mode is not permitted based on task complexity — the only exception is when no team creation tool is available in the current runtime (see no-team fallback in the paragraph below).
|
|
10
|
+
Implement is a **team-first** flow. Bug, Build, Improve, and Investigate-Only all compose multiple specialists (Reproduce → debug → fix → review → verify). Single-agent mode is not permitted based on task complexity — the only exception is when no team creation or subagent delegation tool is available in the current runtime (see no-team fallback in the paragraph below).
|
|
11
11
|
|
|
12
|
-
If you are NOT already operating inside an agent team (no prior successful team-creation tool call in this session, not spawned into a team context), the very first thing you do is establish team orchestration.
|
|
12
|
+
If you are NOT already operating inside an agent team (no prior successful team-creation or subagent-delegation tool call in this session, not spawned into a team context), the very first thing you do is establish team orchestration.
|
|
13
13
|
|
|
14
|
-
Use
|
|
14
|
+
Use the team tool for the current runtime:
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
- Claude: use `TeamCreate`. If `TeamCreate` has not been loaded yet, first use `ToolSearch` with `query: "select:TeamCreate"` to load its schema.
|
|
17
|
+
- Codex: do not call `TeamCreate`; Codex does not expose that Claude tool. Use `tool_search` with a query like `multi-agent tools` to load `multi_agent_v1`, then use `multi_agent_v1.spawn_agent` for teammate delegation. Treat the first successful `spawn_agent` call as establishing team orchestration.
|
|
18
|
+
- Other runtimes: use the current runtime's tool-discovery mechanism to discover and call the appropriate multi-agent/team tool.
|
|
19
|
+
|
|
20
|
+
If no team creation or subagent delegation tool is available, explicitly state that team orchestration is unavailable in this runtime, continue as the lead agent, and preserve the workflow's review, verification, and task-tracking obligations locally. Every team must include the Explore agent.
|
|
21
|
+
|
|
22
|
+
Until the team is established, the first Codex teammate has been spawned, or the no-team fallback has been declared, do NOT call any of: `Agent`, `TaskCreate`, `Skill` (including `lisa:tracker-read`, `lisa:jira-read-ticket`, `lisa:github-read-issue`), MCP tools (Atlassian / Linear / GitHub / Notion), `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`. Reading the ticket, exploring the code, fetching context — every one of those is a task for the team you are about to create, not for the lead session before orchestration exists. Doing them inline is the exact bypass path that produces a 1-agent ad-hoc fix instead of a real team flow.
|
|
17
23
|
|
|
18
24
|
If you ARE already inside an agent team (e.g., a teammate invoked this skill via the Skill tool, or `lisa:intake` is running this skill per Ready ticket), do NOT create a second team — many harnesses reject double-creates. Continue within the existing team. The team lead created the team; teammates inherit it.
|
|
19
25
|
|