@@ -8,6 +8,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
88 */
99
1010const queryMock = vi . fn ( ) ;
11+ const knownTablesMock = vi . fn ( ) ;
1112
1213vi . mock ( "../../src/config.js" , ( ) => ( {
1314 loadConfig : vi . fn ( ) ,
@@ -23,6 +24,7 @@ vi.mock("../../src/deeplake-api.js", () => ({
2324 _tableName : string ,
2425 ) { /* nothing */ }
2526 query ( sql : string ) { return queryMock ( sql ) ; }
27+ async knownTablesOrNull ( ) { return knownTablesMock ( ) ; }
2628 } ,
2729} ) ) ;
2830
@@ -55,6 +57,9 @@ beforeEach(() => {
5557 logged = [ ] ;
5658 erred = [ ] ;
5759 queryMock . mockReset ( ) . mockResolvedValue ( [ ] ) ;
60+ // Default: untrusted table list (null) → renderer SELECTs unconditionally.
61+ // Individual tests override to return a trusted list and exercise gating.
62+ knownTablesMock . mockReset ( ) . mockResolvedValue ( null ) ;
5863 loadConfigMock . mockReset ( ) . mockReturnValue ( VALID_CONFIG ) ;
5964 logSpy = vi . spyOn ( console , "log" ) . mockImplementation ( ( ...a : any [ ] ) => { logged . push ( a . join ( " " ) ) ; } ) ;
6065 errSpy = vi . spyOn ( console , "error" ) . mockImplementation ( ( ...a : any [ ] ) => { erred . push ( a . join ( " " ) ) ; } ) ;
@@ -151,6 +156,32 @@ describe("runContextCommand — output", () => {
151156 expect ( erred . some ( l => l . includes ( "(no active rules or open goals)" ) ) ) . toBe ( true ) ;
152157 } ) ;
153158
159+ it ( "gates the SELECTs on knownTablesOrNull when the table list is trusted" , async ( ) => {
160+ // A non-null table list lets renderContextBlock skip the SELECT for any
161+ // absent table (avoids a 42P01 server-side). Both present here, so both
162+ // SELECTs still run — and the tableExists predicate is exercised.
163+ knownTablesMock . mockResolvedValue ( [ "hivemind_rules" , "hivemind_goals" ] ) ;
164+ queryMock . mockResolvedValueOnce ( [ {
165+ id : "row-1" , rule_id : "rule-1" , text : "no DROP TABLE on prod" ,
166+ scope : "team" , status : "active" , assigned_by : "alice@activeloop.ai" ,
167+ version : 1 , created_at : "2026-05-20T10:00:00Z" ,
168+ agent : "manual" , plugin_version : "0.7.99" ,
169+ } ] ) ;
170+ queryMock . mockResolvedValueOnce ( [ ] ) ; // goals empty
171+ await runContextCommand ( [ ] ) ;
172+ expect ( logged . some ( l => l . includes ( "no DROP TABLE on prod" ) ) ) . toBe ( true ) ;
173+ expect ( queryMock ) . toHaveBeenCalledTimes ( 2 ) ;
174+ } ) ;
175+
176+ it ( "skips every SELECT when the trusted table list omits rules + goals" , async ( ) => {
177+ // Fresh workspace: knownTablesOrNull returns [] → no SELECT may fire
178+ // (each would log a 42P01 server-side). Empty render → stderr diagnostic.
179+ knownTablesMock . mockResolvedValue ( [ ] ) ;
180+ await runContextCommand ( [ ] ) ;
181+ expect ( queryMock ) . not . toHaveBeenCalled ( ) ;
182+ expect ( erred . some ( l => l . includes ( "(no active rules or open goals)" ) ) ) . toBe ( true ) ;
183+ } ) ;
184+
154185 it ( "uses the configured table names from cfg (not hardcoded)" , async ( ) => {
155186 loadConfigMock . mockReturnValueOnce ( {
156187 ...VALID_CONFIG ,
0 commit comments