Explicit cursor is irrelevant.
The lack of binds means that you get a sql statement optimised every time for the unique combination of values supplied.
The main influences for optimizer are statistics and parameters.
Gathering statistics by default is done with no_invalidate of TRUE so that related existing execution plans are not all invalidate at the same time potentially causing a rush of hard parsing.
For further comment, more information is required.
You can extract past plans from AWR using DBMS_XPLAN.DISPLAY_AWR (subject to diagnostic license).
If the SQL you issued outside of the package is identical to the one issued from inside the package, then both of them should have the same SQL ID.
When you run the SQL from outside the package, you should see one entry in V$SQL_SHARED_CURSOR for the SQL ID.
When you run the SQL from inside the package, you should see another entry in V$SQL_SHARED_CURSOR for the same SQL ID.
Reviewing those two records in V$SQL_SHARED_CURSOR might give you a clue.