@codyswann/lisa 1.85.9 → 1.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/configs/jest/base.d.ts +15 -0
- package/dist/configs/jest/base.d.ts.map +1 -1
- package/dist/configs/jest/base.js +18 -0
- package/dist/configs/jest/base.js.map +1 -1
- package/dist/configs/jest/expo.d.ts +2 -2
- package/dist/configs/jest/expo.d.ts.map +1 -1
- package/dist/configs/jest/expo.js +8 -3
- package/dist/configs/jest/expo.js.map +1 -1
- package/dist/configs/jest/typescript.d.ts +2 -2
- package/dist/configs/jest/typescript.d.ts.map +1 -1
- package/dist/configs/jest/typescript.js +7 -3
- package/dist/configs/jest/typescript.js.map +1 -1
- package/expo/copy-overwrite/jest.expo.ts +8 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/commands/plan/execute.md +1 -1
- package/plugins/lisa/rules/base-rules.md +7 -0
- package/plugins/lisa/rules/intent-routing.md +37 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +15 -3
- package/plugins/lisa-nestjs/hooks/block-migration-edits.sh +60 -0
- package/plugins/lisa-nestjs/skills/nestjs-rules/SKILL.md +32 -3
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/commands/plan/execute.md +1 -1
- package/plugins/src/base/rules/base-rules.md +7 -0
- package/plugins/src/base/rules/intent-routing.md +37 -0
- package/plugins/src/nestjs/.claude-plugin/plugin.json +14 -2
- package/plugins/src/nestjs/hooks/block-migration-edits.sh +60 -0
- package/plugins/src/nestjs/skills/nestjs-rules/SKILL.md +32 -3
|
@@ -16,6 +16,21 @@ import type { Config } from "jest";
|
|
|
16
16
|
* Projects can override via jest.thresholds.json.
|
|
17
17
|
*/
|
|
18
18
|
export declare const defaultThresholds: Config["coverageThreshold"];
|
|
19
|
+
/**
|
|
20
|
+
* Returns the extra `testPathIgnorePatterns` entries a stack config
|
|
21
|
+
* should add to skip tests that live inside `.claude/worktrees/`.
|
|
22
|
+
*
|
|
23
|
+
* When jest runs from the primary checkout, tests inside worktrees
|
|
24
|
+
* should be skipped — each worktree has its own jest run. When jest
|
|
25
|
+
* runs from INSIDE a worktree (rootDir *is* the worktree), the same
|
|
26
|
+
* pattern would match every test path and jest would find zero tests.
|
|
27
|
+
* This helper returns `["/.claude/worktrees/"]` only when the current
|
|
28
|
+
* working directory is outside a worktree, so each stack can spread
|
|
29
|
+
* it into its own `testPathIgnorePatterns` without hand-rolling the
|
|
30
|
+
* conditional.
|
|
31
|
+
* @returns Single-entry array with the worktree ignore pattern, or an empty array when already inside a worktree.
|
|
32
|
+
*/
|
|
33
|
+
export declare function worktreeTestPathIgnorePatterns(): readonly string[];
|
|
19
34
|
/**
|
|
20
35
|
* Default patterns to exclude from coverage collection.
|
|
21
36
|
* Common across all stacks — stack-specific configs extend this list.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAOzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAatD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,aAChB,MAAM,CAAC,mBAAmB,CAAC,aAC1B,MAAM,CAAC,mBAAmB,CAAC,KACrC,MAAM,CAAC,mBAAmB,CAO3B,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,eAAgB,MAAM,EAAE,KAAG,MAyBjD,CAAC"}
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAOzD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,IAAI,SAAS,MAAM,EAAE,CAMlE;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAatD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,aAChB,MAAM,CAAC,mBAAmB,CAAC,aAC1B,MAAM,CAAC,mBAAmB,CAAC,KACrC,MAAM,CAAC,mBAAmB,CAO3B,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,eAAgB,MAAM,EAAE,KAAG,MAyBjD,CAAC"}
|
|
@@ -10,6 +10,24 @@ export const defaultThresholds = {
|
|
|
10
10
|
lines: 70,
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Returns the extra `testPathIgnorePatterns` entries a stack config
|
|
15
|
+
* should add to skip tests that live inside `.claude/worktrees/`.
|
|
16
|
+
*
|
|
17
|
+
* When jest runs from the primary checkout, tests inside worktrees
|
|
18
|
+
* should be skipped — each worktree has its own jest run. When jest
|
|
19
|
+
* runs from INSIDE a worktree (rootDir *is* the worktree), the same
|
|
20
|
+
* pattern would match every test path and jest would find zero tests.
|
|
21
|
+
* This helper returns `["/.claude/worktrees/"]` only when the current
|
|
22
|
+
* working directory is outside a worktree, so each stack can spread
|
|
23
|
+
* it into its own `testPathIgnorePatterns` without hand-rolling the
|
|
24
|
+
* conditional.
|
|
25
|
+
* @returns Single-entry array with the worktree ignore pattern, or an empty array when already inside a worktree.
|
|
26
|
+
*/
|
|
27
|
+
export function worktreeTestPathIgnorePatterns() {
|
|
28
|
+
const isInsideWorktree = /[/\\]\.claude[/\\]worktrees(?:[/\\]|$)/.test(process.cwd());
|
|
29
|
+
return isInsideWorktree ? [] : ["/.claude/worktrees/"];
|
|
30
|
+
}
|
|
13
31
|
/**
|
|
14
32
|
* Default patterns to exclude from coverage collection.
|
|
15
33
|
* Common across all stacks — stack-specific configs extend this list.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/configs/jest/base.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgC;IAC5D,MAAM,EAAE;QACN,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,KAAK,EAAE,EAAE;KACV;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,YAAY;IACZ,cAAc;IACd,qBAAqB;IACrB,aAAa;IACb,eAAe;IACf,eAAe;IACf,eAAe;IACf,aAAa;IACb,cAAc;IACd,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;CACvB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAAqC,EACrC,SAAsC,EACT,EAAE,CAAC,CAAC;IACjC,GAAG,QAAQ;IACX,GAAG,SAAS;IACZ,MAAM,EAAE;QACN,GAAI,QAAQ,EAAE,MAAiC;QAC/C,GAAI,SAAS,EAAE,MAAiC;KACjD;CACF,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,OAAiB,EAAU,EAAE,CAC3D,OAAO,CAAC,MAAM,CACZ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAsB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAE9B,MAAM,WAAW,GACf,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAC/C,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ;YACxB,MAAM,KAAK,IAAI;YACf,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,OAAO,SAAS,KAAK,QAAQ;YAC7B,SAAS,KAAK,IAAI;YAClB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3B,CAAC,CAAC;gBACE,GAAI,MAAkC;gBACtC,GAAI,SAAqC;aAC1C;YACH,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC;AAC3C,CAAC,EAAE,GAAG,CAAC,EACT,EAAY,CACb,CAAC"}
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/configs/jest/base.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAgC;IAC5D,MAAM,EAAE;QACN,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,KAAK,EAAE,EAAE;KACV;CACF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,8BAA8B;IAC5C,MAAM,gBAAgB,GAAG,wCAAwC,CAAC,IAAI,CACpE,OAAO,CAAC,GAAG,EAAE,CACd,CAAC;IAEF,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,YAAY;IACZ,cAAc;IACd,qBAAqB;IACrB,aAAa;IACb,eAAe;IACf,eAAe;IACf,eAAe;IACf,aAAa;IACb,cAAc;IACd,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;CACvB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAAqC,EACrC,SAAsC,EACT,EAAE,CAAC,CAAC;IACjC,GAAG,QAAQ;IACX,GAAG,SAAS;IACZ,MAAM,EAAE;QACN,GAAI,QAAQ,EAAE,MAAiC;QAC/C,GAAI,SAAS,EAAE,MAAiC;KACjD;CACF,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,OAAiB,EAAU,EAAE,CAC3D,OAAO,CAAC,MAAM,CACZ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAsB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAE9B,MAAM,WAAW,GACf,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAC/C,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ;YACxB,MAAM,KAAK,IAAI;YACf,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACtB,OAAO,SAAS,KAAK,QAAQ;YAC7B,SAAS,KAAK,IAAI;YAClB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3B,CAAC,CAAC;gBACE,GAAI,MAAkC;gBACtC,GAAI,SAAqC;aAC1C;YACH,CAAC,CAAC,SAAS,CAAC;IAElB,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC;AAC3C,CAAC,EAAE,GAAG,CAAC,EACT,EAAY,CACb,CAAC"}
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
* @module configs/jest/expo
|
|
33
33
|
*/
|
|
34
34
|
import type { Config } from "jest";
|
|
35
|
-
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds } from "./base.js";
|
|
36
|
-
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, };
|
|
35
|
+
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns } from "./base.js";
|
|
36
|
+
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, };
|
|
37
37
|
/**
|
|
38
38
|
* Options for configuring the Expo Jest config factory.
|
|
39
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/expo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/expo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,EAC/B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,CAAC;AAEF;;GAEG;AACH,UAAU,eAAe;IACvB,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;CACnD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,qBAE3B,eAAe,KAAQ,MAmDxB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, } from "./base.js";
|
|
1
|
+
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, } from "./base.js";
|
|
2
2
|
// Re-export base utilities for entry-point configs
|
|
3
|
-
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, };
|
|
3
|
+
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, };
|
|
4
4
|
/**
|
|
5
5
|
* Creates a Jest configuration for Expo/React Native projects.
|
|
6
6
|
* @param options - Configuration options for threshold overrides
|
|
@@ -33,7 +33,12 @@ export const getExpoJestConfig = ({ thresholds = defaultThresholds, } = {}) => (
|
|
|
33
33
|
"^.+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp|ttf|otf|woff|woff2)$": "jest-expo/src/preset/assetFileTransformer.js",
|
|
34
34
|
},
|
|
35
35
|
testMatch: ["<rootDir>/**/*.test.ts", "<rootDir>/**/*.test.tsx"],
|
|
36
|
-
testPathIgnorePatterns: [
|
|
36
|
+
testPathIgnorePatterns: [
|
|
37
|
+
"/node_modules/",
|
|
38
|
+
"/dist/",
|
|
39
|
+
"/.expo/",
|
|
40
|
+
...worktreeTestPathIgnorePatterns(),
|
|
41
|
+
],
|
|
37
42
|
transformIgnorePatterns: [
|
|
38
43
|
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg|@gluestack-ui/.*|@gluestack-style/.*|nativewind|react-native-css-interop|react-native-reanimated|react-native-worklets|lucide-react-native|@gorhom|@shopify)",
|
|
39
44
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo.js","sourceRoot":"","sources":["../../../src/configs/jest/expo.ts"],"names":[],"mappings":"AAmCA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"expo.js","sourceRoot":"","sources":["../../../src/configs/jest/expo.ts"],"names":[],"mappings":"AAmCA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,MAAM,WAAW,CAAC;AAEnB,mDAAmD;AACnD,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,CAAC;AAUF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAChC,UAAU,GAAG,iBAAiB,MACX,EAAE,EAAU,EAAE,CAAC,CAAC;IACnC,eAAe,EAAE,OAAO;IACxB,KAAK,EAAE;QACL,eAAe,EAAE,KAAK;QACtB,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC;KACxC;IACD,QAAQ,EAAE,+BAA+B;IACzC,UAAU,EAAE,CAAC,6BAA6B,CAAC;IAC3C,kBAAkB,EAAE,CAAC,yBAAyB,CAAC;IAC/C,SAAS,EAAE;QACT,aAAa,EAAE;YACb,YAAY;YACZ;gBACE,MAAM,EAAE;oBACN,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,OAAO;oBAChB,QAAQ,EAAE,KAAK;iBAChB;aACF;SACF;QACD,mEAAmE,EACjE,8CAA8C;KACjD;IACD,SAAS,EAAE,CAAC,wBAAwB,EAAE,yBAAyB,CAAC;IAChE,sBAAsB,EAAE;QACtB,gBAAgB;QAChB,QAAQ;QACR,SAAS;QACT,GAAG,8BAA8B,EAAE;KACpC;IACD,uBAAuB,EAAE;QACvB,0WAA0W;KAC3W;IACD,oBAAoB,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;IAChE,mBAAmB,EAAE;QACnB,0BAA0B;QAC1B,sBAAsB;QACtB,yBAAyB;QACzB,wBAAwB;QACxB,qBAAqB;QACrB,mBAAmB;QACnB,yBAAyB;QACzB,sBAAsB;QACtB,sBAAsB;QACtB,qBAAqB;QACrB,qBAAqB;QACrB,oBAAoB;QACpB,GAAG,yBAAyB;KAC7B;IACD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,WAAW,EAAE,KAAK;CACnB,CAAC,CAAC"}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* @module configs/jest/typescript
|
|
9
9
|
*/
|
|
10
10
|
import type { Config } from "jest";
|
|
11
|
-
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds } from "./base.js";
|
|
12
|
-
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, };
|
|
11
|
+
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns } from "./base.js";
|
|
12
|
+
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, };
|
|
13
13
|
/**
|
|
14
14
|
* Options for configuring the TypeScript Jest config factory.
|
|
15
15
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/typescript.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/configs/jest/typescript.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,EAC/B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,CAAC;AAEF;;GAEG;AACH,UAAU,qBAAqB;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,qBAEjC,qBAAqB,KAAQ,MAwB9B,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, } from "./base.js";
|
|
1
|
+
import { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, } from "./base.js";
|
|
2
2
|
// Re-export base utilities for stack-specific configs to use
|
|
3
|
-
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, };
|
|
3
|
+
export { defaultCoverageExclusions, defaultThresholds, mergeConfigs, mergeThresholds, worktreeTestPathIgnorePatterns, };
|
|
4
4
|
/**
|
|
5
5
|
* Creates a Jest configuration for TypeScript/Node projects using ts-jest.
|
|
6
6
|
* @param options - Configuration options for threshold overrides
|
|
@@ -13,7 +13,11 @@ export const getTypescriptJestConfig = ({ thresholds = defaultThresholds, } = {}
|
|
|
13
13
|
preset: "ts-jest/presets/default-esm",
|
|
14
14
|
testEnvironment: "node",
|
|
15
15
|
testMatch: ["<rootDir>/tests/**/*.test.ts", "<rootDir>/src/**/*.test.ts"],
|
|
16
|
-
testPathIgnorePatterns: [
|
|
16
|
+
testPathIgnorePatterns: [
|
|
17
|
+
"/node_modules/",
|
|
18
|
+
"/dist/",
|
|
19
|
+
...worktreeTestPathIgnorePatterns(),
|
|
20
|
+
],
|
|
17
21
|
moduleNameMapper: {
|
|
18
22
|
"^(\\.{1,2}/.*)\\.js$": "$1",
|
|
19
23
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/configs/jest/typescript.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,
|
|
1
|
+
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/configs/jest/typescript.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,MAAM,WAAW,CAAC;AAEnB,6DAA6D;AAC7D,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,8BAA8B,GAC/B,CAAC;AAUF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EACtC,UAAU,GAAG,iBAAiB,MACL,EAAE,EAAU,EAAE,CAAC,CAAC;IACzC,MAAM,EAAE,6BAA6B;IACrC,eAAe,EAAE,MAAM;IACvB,SAAS,EAAE,CAAC,8BAA8B,EAAE,4BAA4B,CAAC;IACzE,sBAAsB,EAAE;QACtB,gBAAgB;QAChB,QAAQ;QACR,GAAG,8BAA8B,EAAE;KACpC;IACD,gBAAgB,EAAE;QAChB,sBAAsB,EAAE,IAAI;KAC7B;IACD,SAAS,EAAE;QACT,aAAa,EAAE;YACb,SAAS;YACT;gBACE,MAAM,EAAE,IAAI;aACb;SACF;KACF;IACD,sBAAsB,EAAE,CAAC,KAAK,CAAC;IAC/B,mBAAmB,EAAE,CAAC,aAAa,EAAE,GAAG,yBAAyB,CAAC;IAClE,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,WAAW,EAAE,KAAK;CACnB,CAAC,CAAC"}
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
defaultThresholds,
|
|
45
45
|
mergeConfigs,
|
|
46
46
|
mergeThresholds,
|
|
47
|
+
worktreeTestPathIgnorePatterns,
|
|
47
48
|
} from "@codyswann/lisa/jest/base";
|
|
48
49
|
|
|
49
50
|
// Re-export base utilities for entry-point configs
|
|
@@ -52,6 +53,7 @@ export {
|
|
|
52
53
|
defaultThresholds,
|
|
53
54
|
mergeConfigs,
|
|
54
55
|
mergeThresholds,
|
|
56
|
+
worktreeTestPathIgnorePatterns,
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
/**
|
|
@@ -98,7 +100,12 @@ export const getExpoJestConfig = ({
|
|
|
98
100
|
"jest-expo/src/preset/assetFileTransformer.js",
|
|
99
101
|
},
|
|
100
102
|
testMatch: ["<rootDir>/**/*.test.ts", "<rootDir>/**/*.test.tsx"],
|
|
101
|
-
testPathIgnorePatterns: [
|
|
103
|
+
testPathIgnorePatterns: [
|
|
104
|
+
"/node_modules/",
|
|
105
|
+
"/dist/",
|
|
106
|
+
"/.expo/",
|
|
107
|
+
...worktreeTestPathIgnorePatterns(),
|
|
108
|
+
],
|
|
102
109
|
transformIgnorePatterns: [
|
|
103
110
|
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg|@gluestack-ui/.*|@gluestack-style/.*|nativewind|react-native-css-interop|react-native-reanimated|react-native-worklets|lucide-react-native|@gorhom|@shopify)",
|
|
104
111
|
],
|
package/package.json
CHANGED
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"lodash": ">=4.18.1"
|
|
79
79
|
},
|
|
80
80
|
"name": "@codyswann/lisa",
|
|
81
|
-
"version": "1.
|
|
81
|
+
"version": "1.86.0",
|
|
82
82
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
83
83
|
"main": "dist/index.js",
|
|
84
84
|
"exports": {
|
|
@@ -3,4 +3,4 @@ description: "Deploys an agent team to research, implement, review and deploy a
|
|
|
3
3
|
argument-hint: "<ticket-url | @file-path | description>"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Pass through to `/build` with $ARGUMENTS. The Build command reads `.claude/rules/intent-routing.md` and runs the full Implement → Review → Verify chain, which is what this command historically did.
|
|
@@ -72,6 +72,13 @@ JIRA Discipline:
|
|
|
72
72
|
Agent Behavior:
|
|
73
73
|
- Never handle tasks yourself when working in a team of agents. Always delegate to a specialized agent.
|
|
74
74
|
|
|
75
|
+
Pace:
|
|
76
|
+
- Never rush. There is no pressure to finish quickly. Speed is not a measure of quality, and a fast wrong answer is worse than a slow correct one.
|
|
77
|
+
- Take the time to read the relevant code in full, verify assumptions empirically, ask clarifying questions when something is ambiguous, and check your work before declaring it done.
|
|
78
|
+
- Do not skip steps to save time — quality gates, verification, reading existing code, asking the user — these exist because shortcuts cost more than they save.
|
|
79
|
+
- If a task feels like it's taking "too long," that is almost always a sign that the task is harder than it first appeared, not a sign that you should cut corners. Surface the difficulty to the user instead of compressing the work.
|
|
80
|
+
- Optimize for being correct, thorough, and reversible. Time spent doing the work right is never wasted; time spent recovering from a rushed answer often is.
|
|
81
|
+
|
|
75
82
|
NEVER:
|
|
76
83
|
- Modify this file directly. To add a memory or learning, use the project's rules file or create a skill.
|
|
77
84
|
- Directly modify files inside dependency directories (e.g. node_modules, .venv, vendor, target).
|
|
@@ -253,3 +253,40 @@ The full lifecycle for a large initiative: Research -> Plan -> Implement (per it
|
|
|
253
253
|
## Sub-flow Usage
|
|
254
254
|
|
|
255
255
|
Flows reference sub-flows by name. When a flow says "Investigate sub-flow", execute the full Investigate sub-flow sequence. When it says "Review sub-flow", execute the full Review sequence. Sub-flows can be invoked by any main flow.
|
|
256
|
+
|
|
257
|
+
## Orchestration
|
|
258
|
+
|
|
259
|
+
How a flow dispatches its agents depends on the flow's shape. Pick the orchestration mode that matches the work — do not default to the heaviest one.
|
|
260
|
+
|
|
261
|
+
### Agent Teams (default for multi-step flows)
|
|
262
|
+
|
|
263
|
+
Use an **agent team** (TeamCreate + TaskCreate per step) for:
|
|
264
|
+
|
|
265
|
+
- **Implement** (Build, Fix, Improve) — long sequences with parallel review and a real risk of compaction
|
|
266
|
+
- **Plan** — multiple specialists feeding a shared decomposition
|
|
267
|
+
- **Research** — multiple specialists feeding a shared PRD
|
|
268
|
+
- Any flow that invokes the **Review sub-flow** (the four review specialists run in parallel and gate a single follow-up task)
|
|
269
|
+
|
|
270
|
+
Why: these flows have enough steps that context compaction is likely; the Review sub-flow is parallel-by-design and `blockedBy` expresses that cleanly; durable task state lets the team lead recover assignments after compaction.
|
|
271
|
+
|
|
272
|
+
When using a team:
|
|
273
|
+
|
|
274
|
+
1. Create one team per top-level flow invocation. Do not nest teams for sub-flows — sub-flow steps become tasks within the existing team.
|
|
275
|
+
2. Express parallelism with `blockedBy`. The Review sub-flow's four specialists are independent; the "implement valid suggestions" task is `blockedBy` all four.
|
|
276
|
+
3. On every TaskUpdate that sets `owner`, also store it in `metadata.owner` so the assignment survives context compaction.
|
|
277
|
+
4. Re-read TaskList after any compaction event before assigning new work.
|
|
278
|
+
|
|
279
|
+
### One-shot Sub-agents (for short or single-agent flows)
|
|
280
|
+
|
|
281
|
+
Use direct `Agent` tool invocations (no team) for:
|
|
282
|
+
|
|
283
|
+
- **Verify** when run standalone — it's a linear gate sequence with no parallelism
|
|
284
|
+
- **Monitor** standalone — single specialist (`ops-specialist`) producing a report
|
|
285
|
+
- **Investigate Only** spikes — single investigation, findings out
|
|
286
|
+
- Any flow chained as a sub-flow inside a larger team — its agents become tasks in the parent team, not a new team
|
|
287
|
+
|
|
288
|
+
Why: TeamCreate plus per-step TaskCreate is real overhead. For a one-or-two-agent flow with no parallelism, the bookkeeping cost outweighs the recovery and orchestration benefits.
|
|
289
|
+
|
|
290
|
+
### When in doubt
|
|
291
|
+
|
|
292
|
+
If the flow has more than three agent steps, or any parallel step, or is likely to span a compaction boundary, use a team. Otherwise, sub-agents are fine.
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-nestjs",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "NestJS-specific skills (GraphQL, TypeORM)",
|
|
3
|
+
"version": "1.86.0",
|
|
4
|
+
"description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
7
7
|
},
|
|
8
|
-
"hooks": {
|
|
8
|
+
"hooks": {
|
|
9
|
+
"PreToolUse": [
|
|
10
|
+
{
|
|
11
|
+
"matcher": "Write|Edit",
|
|
12
|
+
"hooks": [
|
|
13
|
+
{
|
|
14
|
+
"type": "command",
|
|
15
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/block-migration-edits.sh"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
9
21
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# This file is managed by Lisa.
|
|
3
|
+
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
+
|
|
5
|
+
# PreToolUse hook: block Write/Edit on TypeORM migration files.
|
|
6
|
+
# NestJS projects must use `bun run migration:generate` to create migrations
|
|
7
|
+
# from entity diffs. Hand-written migrations drift from entity metadata and
|
|
8
|
+
# break the schema/migration contract.
|
|
9
|
+
# Reference: https://docs.claude.com/en/docs/claude-code/hooks
|
|
10
|
+
# Exit code 2 blocks the tool call and surfaces stderr to Claude.
|
|
11
|
+
|
|
12
|
+
JSON_INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
15
|
+
echo "⚠ block-migration-edits: jq not available, allowing edit" >&2
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
FILE_PATH=$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')
|
|
20
|
+
|
|
21
|
+
if [ -z "$FILE_PATH" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
case "$FILE_PATH" in
|
|
26
|
+
*/migrations/*.ts|*/migrations/*.js)
|
|
27
|
+
cat >&2 <<EOF
|
|
28
|
+
❌ Blocked: Direct edits to TypeORM migration files are not allowed.
|
|
29
|
+
|
|
30
|
+
File: $FILE_PATH
|
|
31
|
+
|
|
32
|
+
Entity files (src/database/entities/*.ts) are the single source of
|
|
33
|
+
truth for the database schema in this project. Migrations are a derived
|
|
34
|
+
artifact — generate them from entity diffs:
|
|
35
|
+
|
|
36
|
+
1. Edit the entity to express the desired schema.
|
|
37
|
+
2. Run: bun run migration:generate --name=<DescriptiveName>
|
|
38
|
+
3. Review the generated migration; commit entity + migration together.
|
|
39
|
+
|
|
40
|
+
If a schema change cannot be expressed via the entity model, the entity
|
|
41
|
+
model is wrong — fix the entity, do not hand-write the migration.
|
|
42
|
+
|
|
43
|
+
OUT-OF-BAND MIGRATIONS (seed data, backfills, data transformations,
|
|
44
|
+
one-off cleanup): these genuinely cannot come from entity diffs. They
|
|
45
|
+
are legitimate but they bypass the entity-as-source-of-truth contract.
|
|
46
|
+
|
|
47
|
+
If you believe this edit is an out-of-band migration:
|
|
48
|
+
1. STOP and tell the user what change is needed and why it cannot
|
|
49
|
+
be expressed via the entity model.
|
|
50
|
+
2. Get explicit approval before proceeding.
|
|
51
|
+
3. Document the rationale in the migration's class comment.
|
|
52
|
+
|
|
53
|
+
Do NOT silently hand-write a migration. See the nestjs-rules skill
|
|
54
|
+
for the full rationale.
|
|
55
|
+
EOF
|
|
56
|
+
exit 2
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
59
|
+
|
|
60
|
+
exit 0
|
|
@@ -43,15 +43,44 @@ The `--no-spec` flag is used because this project follows TDD (Test-Driven Devel
|
|
|
43
43
|
|
|
44
44
|
## Database Migrations
|
|
45
45
|
|
|
46
|
+
### Entity Files Are the Source of Truth
|
|
47
|
+
|
|
48
|
+
In this project, **entity files (`src/database/entities/*.ts`) are the single source of truth for the database schema**. Migrations are a derived artifact — TypeORM diffs the entity metadata against the current database and emits the migration for you. The workflow is always:
|
|
49
|
+
|
|
50
|
+
1. Edit the entity file to express the desired schema.
|
|
51
|
+
2. Run `bun run migration:generate --name=<DescriptiveName>` to produce the migration from the diff.
|
|
52
|
+
3. Review the generated migration, then commit both the entity change and the migration together.
|
|
53
|
+
|
|
54
|
+
If a schema change cannot be expressed via the entity model, the entity model is wrong — fix the entity, do not hand-write the migration.
|
|
55
|
+
|
|
46
56
|
### Never Create Migration Files Manually
|
|
47
57
|
|
|
48
|
-
Never create or modify a TypeORM migration file directly.
|
|
58
|
+
Never create or modify a TypeORM migration file directly. Use `migration:generate` from `package.json`:
|
|
49
59
|
|
|
50
60
|
```bash
|
|
51
|
-
bun run migration:generate
|
|
61
|
+
bun run migration:generate --name=<DescriptiveName>
|
|
52
62
|
```
|
|
53
63
|
|
|
54
|
-
|
|
64
|
+
### Out-of-Band Migrations (Seed Data, Backfills)
|
|
65
|
+
|
|
66
|
+
Some changes genuinely cannot be derived from entity diffs:
|
|
67
|
+
|
|
68
|
+
- **Seed data** (reference rows, lookup tables, initial admin user)
|
|
69
|
+
- **Data backfills** (populating a new column from existing rows)
|
|
70
|
+
- **Data transformations** (splitting a column, normalizing values)
|
|
71
|
+
- **One-off cleanup** (deleting orphaned rows before a constraint is added)
|
|
72
|
+
|
|
73
|
+
These are legitimate cases for a hand-written migration, but they are **out-of-band** — they bypass the entity-as-source-of-truth contract. When you encounter one:
|
|
74
|
+
|
|
75
|
+
1. **Stop and tell the user.** Explain what change is needed and why it cannot be expressed via the entity model.
|
|
76
|
+
2. **Get explicit approval** before writing the migration by hand.
|
|
77
|
+
3. Document the rationale in the migration's class comment so future readers understand why this one was not generated.
|
|
78
|
+
|
|
79
|
+
Do not silently hand-write a migration for a backfill or seed-data change. The user must know that the entity-as-source-of-truth contract is being intentionally bypassed for this case.
|
|
80
|
+
|
|
81
|
+
### Enforcement
|
|
82
|
+
|
|
83
|
+
The `lisa-nestjs` plugin ships a `PreToolUse` hook (`block-migration-edits.sh`) that blocks `Write`/`Edit` on any path matching `**/migrations/*.ts` or `**/migrations/*.js`. The block surfaces this rule's guidance to remind you to either (a) edit the entity instead, or (b) ask the user before proceeding with an out-of-band migration.
|
|
55
84
|
|
|
56
85
|
### Why Auto-Generation
|
|
57
86
|
|
|
@@ -3,4 +3,4 @@ description: "Deploys an agent team to research, implement, review and deploy a
|
|
|
3
3
|
argument-hint: "<ticket-url | @file-path | description>"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Pass through to `/build` with $ARGUMENTS. The Build command reads `.claude/rules/intent-routing.md` and runs the full Implement → Review → Verify chain, which is what this command historically did.
|
|
@@ -72,6 +72,13 @@ JIRA Discipline:
|
|
|
72
72
|
Agent Behavior:
|
|
73
73
|
- Never handle tasks yourself when working in a team of agents. Always delegate to a specialized agent.
|
|
74
74
|
|
|
75
|
+
Pace:
|
|
76
|
+
- Never rush. There is no pressure to finish quickly. Speed is not a measure of quality, and a fast wrong answer is worse than a slow correct one.
|
|
77
|
+
- Take the time to read the relevant code in full, verify assumptions empirically, ask clarifying questions when something is ambiguous, and check your work before declaring it done.
|
|
78
|
+
- Do not skip steps to save time — quality gates, verification, reading existing code, asking the user — these exist because shortcuts cost more than they save.
|
|
79
|
+
- If a task feels like it's taking "too long," that is almost always a sign that the task is harder than it first appeared, not a sign that you should cut corners. Surface the difficulty to the user instead of compressing the work.
|
|
80
|
+
- Optimize for being correct, thorough, and reversible. Time spent doing the work right is never wasted; time spent recovering from a rushed answer often is.
|
|
81
|
+
|
|
75
82
|
NEVER:
|
|
76
83
|
- Modify this file directly. To add a memory or learning, use the project's rules file or create a skill.
|
|
77
84
|
- Directly modify files inside dependency directories (e.g. node_modules, .venv, vendor, target).
|
|
@@ -253,3 +253,40 @@ The full lifecycle for a large initiative: Research -> Plan -> Implement (per it
|
|
|
253
253
|
## Sub-flow Usage
|
|
254
254
|
|
|
255
255
|
Flows reference sub-flows by name. When a flow says "Investigate sub-flow", execute the full Investigate sub-flow sequence. When it says "Review sub-flow", execute the full Review sequence. Sub-flows can be invoked by any main flow.
|
|
256
|
+
|
|
257
|
+
## Orchestration
|
|
258
|
+
|
|
259
|
+
How a flow dispatches its agents depends on the flow's shape. Pick the orchestration mode that matches the work — do not default to the heaviest one.
|
|
260
|
+
|
|
261
|
+
### Agent Teams (default for multi-step flows)
|
|
262
|
+
|
|
263
|
+
Use an **agent team** (TeamCreate + TaskCreate per step) for:
|
|
264
|
+
|
|
265
|
+
- **Implement** (Build, Fix, Improve) — long sequences with parallel review and a real risk of compaction
|
|
266
|
+
- **Plan** — multiple specialists feeding a shared decomposition
|
|
267
|
+
- **Research** — multiple specialists feeding a shared PRD
|
|
268
|
+
- Any flow that invokes the **Review sub-flow** (the four review specialists run in parallel and gate a single follow-up task)
|
|
269
|
+
|
|
270
|
+
Why: these flows have enough steps that context compaction is likely; the Review sub-flow is parallel-by-design and `blockedBy` expresses that cleanly; durable task state lets the team lead recover assignments after compaction.
|
|
271
|
+
|
|
272
|
+
When using a team:
|
|
273
|
+
|
|
274
|
+
1. Create one team per top-level flow invocation. Do not nest teams for sub-flows — sub-flow steps become tasks within the existing team.
|
|
275
|
+
2. Express parallelism with `blockedBy`. The Review sub-flow's four specialists are independent; the "implement valid suggestions" task is `blockedBy` all four.
|
|
276
|
+
3. On every TaskUpdate that sets `owner`, also store it in `metadata.owner` so the assignment survives context compaction.
|
|
277
|
+
4. Re-read TaskList after any compaction event before assigning new work.
|
|
278
|
+
|
|
279
|
+
### One-shot Sub-agents (for short or single-agent flows)
|
|
280
|
+
|
|
281
|
+
Use direct `Agent` tool invocations (no team) for:
|
|
282
|
+
|
|
283
|
+
- **Verify** when run standalone — it's a linear gate sequence with no parallelism
|
|
284
|
+
- **Monitor** standalone — single specialist (`ops-specialist`) producing a report
|
|
285
|
+
- **Investigate Only** spikes — single investigation, findings out
|
|
286
|
+
- Any flow chained as a sub-flow inside a larger team — its agents become tasks in the parent team, not a new team
|
|
287
|
+
|
|
288
|
+
Why: TeamCreate plus per-step TaskCreate is real overhead. For a one-or-two-agent flow with no parallelism, the bookkeeping cost outweighs the recovery and orchestration benefits.
|
|
289
|
+
|
|
290
|
+
### When in doubt
|
|
291
|
+
|
|
292
|
+
If the flow has more than three agent steps, or any parallel step, or is likely to span a compaction boundary, use a team. Otherwise, sub-agents are fine.
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-nestjs",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "NestJS-specific skills (GraphQL, TypeORM)",
|
|
4
|
+
"description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
|
|
5
5
|
"author": { "name": "Cody Swann" },
|
|
6
|
-
"hooks": {
|
|
6
|
+
"hooks": {
|
|
7
|
+
"PreToolUse": [
|
|
8
|
+
{
|
|
9
|
+
"matcher": "Write|Edit",
|
|
10
|
+
"hooks": [
|
|
11
|
+
{
|
|
12
|
+
"type": "command",
|
|
13
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/block-migration-edits.sh"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
7
19
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# This file is managed by Lisa.
|
|
3
|
+
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
+
|
|
5
|
+
# PreToolUse hook: block Write/Edit on TypeORM migration files.
|
|
6
|
+
# NestJS projects must use `bun run migration:generate` to create migrations
|
|
7
|
+
# from entity diffs. Hand-written migrations drift from entity metadata and
|
|
8
|
+
# break the schema/migration contract.
|
|
9
|
+
# Reference: https://docs.claude.com/en/docs/claude-code/hooks
|
|
10
|
+
# Exit code 2 blocks the tool call and surfaces stderr to Claude.
|
|
11
|
+
|
|
12
|
+
JSON_INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
15
|
+
echo "⚠ block-migration-edits: jq not available, allowing edit" >&2
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
FILE_PATH=$(echo "$JSON_INPUT" | jq -r '.tool_input.file_path // empty')
|
|
20
|
+
|
|
21
|
+
if [ -z "$FILE_PATH" ]; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
case "$FILE_PATH" in
|
|
26
|
+
*/migrations/*.ts|*/migrations/*.js)
|
|
27
|
+
cat >&2 <<EOF
|
|
28
|
+
❌ Blocked: Direct edits to TypeORM migration files are not allowed.
|
|
29
|
+
|
|
30
|
+
File: $FILE_PATH
|
|
31
|
+
|
|
32
|
+
Entity files (src/database/entities/*.ts) are the single source of
|
|
33
|
+
truth for the database schema in this project. Migrations are a derived
|
|
34
|
+
artifact — generate them from entity diffs:
|
|
35
|
+
|
|
36
|
+
1. Edit the entity to express the desired schema.
|
|
37
|
+
2. Run: bun run migration:generate --name=<DescriptiveName>
|
|
38
|
+
3. Review the generated migration; commit entity + migration together.
|
|
39
|
+
|
|
40
|
+
If a schema change cannot be expressed via the entity model, the entity
|
|
41
|
+
model is wrong — fix the entity, do not hand-write the migration.
|
|
42
|
+
|
|
43
|
+
OUT-OF-BAND MIGRATIONS (seed data, backfills, data transformations,
|
|
44
|
+
one-off cleanup): these genuinely cannot come from entity diffs. They
|
|
45
|
+
are legitimate but they bypass the entity-as-source-of-truth contract.
|
|
46
|
+
|
|
47
|
+
If you believe this edit is an out-of-band migration:
|
|
48
|
+
1. STOP and tell the user what change is needed and why it cannot
|
|
49
|
+
be expressed via the entity model.
|
|
50
|
+
2. Get explicit approval before proceeding.
|
|
51
|
+
3. Document the rationale in the migration's class comment.
|
|
52
|
+
|
|
53
|
+
Do NOT silently hand-write a migration. See the nestjs-rules skill
|
|
54
|
+
for the full rationale.
|
|
55
|
+
EOF
|
|
56
|
+
exit 2
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
59
|
+
|
|
60
|
+
exit 0
|
|
@@ -43,15 +43,44 @@ The `--no-spec` flag is used because this project follows TDD (Test-Driven Devel
|
|
|
43
43
|
|
|
44
44
|
## Database Migrations
|
|
45
45
|
|
|
46
|
+
### Entity Files Are the Source of Truth
|
|
47
|
+
|
|
48
|
+
In this project, **entity files (`src/database/entities/*.ts`) are the single source of truth for the database schema**. Migrations are a derived artifact — TypeORM diffs the entity metadata against the current database and emits the migration for you. The workflow is always:
|
|
49
|
+
|
|
50
|
+
1. Edit the entity file to express the desired schema.
|
|
51
|
+
2. Run `bun run migration:generate --name=<DescriptiveName>` to produce the migration from the diff.
|
|
52
|
+
3. Review the generated migration, then commit both the entity change and the migration together.
|
|
53
|
+
|
|
54
|
+
If a schema change cannot be expressed via the entity model, the entity model is wrong — fix the entity, do not hand-write the migration.
|
|
55
|
+
|
|
46
56
|
### Never Create Migration Files Manually
|
|
47
57
|
|
|
48
|
-
Never create or modify a TypeORM migration file directly.
|
|
58
|
+
Never create or modify a TypeORM migration file directly. Use `migration:generate` from `package.json`:
|
|
49
59
|
|
|
50
60
|
```bash
|
|
51
|
-
bun run migration:generate
|
|
61
|
+
bun run migration:generate --name=<DescriptiveName>
|
|
52
62
|
```
|
|
53
63
|
|
|
54
|
-
|
|
64
|
+
### Out-of-Band Migrations (Seed Data, Backfills)
|
|
65
|
+
|
|
66
|
+
Some changes genuinely cannot be derived from entity diffs:
|
|
67
|
+
|
|
68
|
+
- **Seed data** (reference rows, lookup tables, initial admin user)
|
|
69
|
+
- **Data backfills** (populating a new column from existing rows)
|
|
70
|
+
- **Data transformations** (splitting a column, normalizing values)
|
|
71
|
+
- **One-off cleanup** (deleting orphaned rows before a constraint is added)
|
|
72
|
+
|
|
73
|
+
These are legitimate cases for a hand-written migration, but they are **out-of-band** — they bypass the entity-as-source-of-truth contract. When you encounter one:
|
|
74
|
+
|
|
75
|
+
1. **Stop and tell the user.** Explain what change is needed and why it cannot be expressed via the entity model.
|
|
76
|
+
2. **Get explicit approval** before writing the migration by hand.
|
|
77
|
+
3. Document the rationale in the migration's class comment so future readers understand why this one was not generated.
|
|
78
|
+
|
|
79
|
+
Do not silently hand-write a migration for a backfill or seed-data change. The user must know that the entity-as-source-of-truth contract is being intentionally bypassed for this case.
|
|
80
|
+
|
|
81
|
+
### Enforcement
|
|
82
|
+
|
|
83
|
+
The `lisa-nestjs` plugin ships a `PreToolUse` hook (`block-migration-edits.sh`) that blocks `Write`/`Edit` on any path matching `**/migrations/*.ts` or `**/migrations/*.js`. The block surfaces this rule's guidance to remind you to either (a) edit the entity instead, or (b) ask the user before proceeding with an out-of-band migration.
|
|
55
84
|
|
|
56
85
|
### Why Auto-Generation
|
|
57
86
|
|